Search code examples
reactjspie-chartrecharts

Recharts : Position label in center of pie slice


I'm pretty new to React so please bear with me

I created a pie chart using Recharts, with custom labels, but I cannot get each label to position itself in the center of its slice. See, for instance, the numbers "20" and "11" in the enter image description here

My code currently looks as follows (the embarrassing truth is most of this comes from samples I f found online)

 <PieChart width={400} height={240} style={{ outline: "none" }}>
      <Pie
        data={data}
        dataKey="value"
        innerRadius={50}
        outerRadius={100}
        labelLine={false}
        label={customDonutLabel}
        style={{ outline: "none" }}
      />
      <Tooltip content={<ChartTooltip />} />
    </PieChart>


const customDonutLabel: PieLabel<CustomDonutLabelRenderProps<ChartDataProps>> = (props) => {
  const slicePercentage = props.payload.value * 100;
  if (slicePercentage < 10) {
    return null;
  }
  const RADIAN = Math.PI / 180;
  const innerRadius = convertToNumber(props.innerRadius);
  const outerRadius = convertToNumber(props.outerRadius);
  const cx = convertToNumber(props.cx);
  const cy = convertToNumber(props.cy);
  const midAngle = convertToNumber(props.midAngle);

  const radius = innerRadius + (outerRadius - innerRadius) * 0.35;
  const x = cx + radius * Math.cos(-midAngle * RADIAN);
  const y = cy + radius * Math.sin(-midAngle * RADIAN);

  return (
    <text
      style={{ fontWeight: "semibold", fontSize: "md" }}
      x={x}
      y={y}
      fill={props.payload.color}
      textAnchor={x > cx ? "start" : "end"}
      dominantBaseline="central"
    >
      {Math.round(props.payload.value * 100)}
    </text>
  );
};

Solution

  • This seems to have done the job

      const outerRadius = convertToNumber(props.outerRadius);
      const cx = convertToNumber(props.cx);
      const cy = convertToNumber(props.cy);
      const midAngle = convertToNumber(props.midAngle);
    
      const RADIAN = Math.PI / 180;
      const radius = innerRadius + (outerRadius - innerRadius) * 0.7;
    
      return (
        <text
          style={{ fontWeight: "semibold", fontSize: "md" }}
          x={cx + radius * Math.cos(-midAngle * RADIAN)}
          y={cy + radius * Math.sin(-midAngle * RADIAN)}
          fill={props.payload.color}
          textAnchor="middle"
          dominantBaseline="middle"
        >
          {Math.round(props.payload.value * 100)}
        </text>
      );