Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

recharts pie chart w/ value labels inside

using the recharts library, i'd love to create a donut chart like this: https://apexcharts.com/javascript-chart-demos/pie-charts/simple-donut/

specifically, the value labels are inside the pie chart segments. the only example i can find in the docs uses a custom renderLabel, but i was hoping with the new label component, this would be easier: http://recharts.org/en-US/examples/PieChartWithCustomizedLabel

and following this example, this is the closest i can get, but the labels are not centered: enter image description here

here is the the new Label component docs. i've tried: <Label position="inside />

here is the code for customLabelRendering:

const RADIAN = Math.PI / 180;
const renderCustomizedLabel = ({
  cx, cy, midAngle, innerRadius, outerRadius, percent, index,
}) => {
   const radius = innerRadius + (outerRadius - innerRadius) * 0.5;
  const x = cx + radius * Math.cos(-midAngle * RADIAN);
  const y = cy + radius * Math.sin(-midAngle * RADIAN);

  return (
    <text x={x} y={y} fill="white" textAnchor={x > cx ? 'start' : 'end'} dominantBaseline="central">
      {`${(percent * 100).toFixed(0)}%`}
    </text>
  );
};
like image 899
jonnie Avatar asked Mar 19 '19 17:03

jonnie


1 Answers

You can align the <text /> label with textAnchor="middle" which will align them in the center for all cells.

Like this:

<text x={x} y={y} fill="white" textAnchor="middle" dominantBaseline="central">
  {`${(percent * 100).toFixed(0)}%`}
</text>

You final code should look like this:

const RADIAN = Math.PI / 180;
const renderCustomizedLabel = ({
  cx, cy, midAngle, innerRadius, outerRadius, percent, index,
}) => {
   const radius = innerRadius + (outerRadius - innerRadius) * 0.5;
  const x = cx + radius * Math.cos(-midAngle * RADIAN);
  const y = cy + radius * Math.sin(-midAngle * RADIAN);

  return (
    <text x={x} y={y} fill="white" textAnchor="middle" dominantBaseline="central">
      {`${(percent * 100).toFixed(0)}%`}
    </text>
  );
}

The above works for text, but if you need images in the center use <svg /> and <image />.

return (
  <svg
    x={x - 12}
    y={y - 12}
    fill="#666"
    textAnchor={"middle"}
    dominantBaseline="central"
    width={24}
    height={24}
    viewBox="0 0 1024 1024"
  >
    <image
      href="https://mdn.mozillademos.org/files/6457/mdn_logo_only_color.png"
      height="100%"
      width="100%"
    />
  </svg>
);

enter image description here

like image 169
Rusty Avatar answered Oct 27 '22 22:10

Rusty