`I’m working on a React project where I’m using Re-charts to create a donuts chart. I have a custom label that I want to display as an arrow pointing to a specific section of the chart. The label(text and its above the arrow) should be responsive and adjust its size based on the chart’s dimensions. Here’s a simplified version of my code:
import React, { useCallback, useState } from 'react';
import {
ResponsiveContainer,
PieChart,
Pie,
Tooltip,
Cell,
Legend,
Sector,
} from 'recharts';
const data = [
{ name: 'Group A', value: 400 },
{ name: 'Group B', value: 300 },
{ name: 'Group C', value: 300 },
{ name: 'Group D', value: 200 },
];
const COLORS = ['#0088FE', '#00C49F', '#FFBB28', '#FF8042'];
const myStyles = {
fontFamily: 'sans-serif',
textAlign: 'center',
};
const mystyle = {
gridContainer: {
width: '100vw',
height: '100vh',
}
};
const renderActiveShape = (props: any) => {
const RADIAN = Math.PI / 180;
const {
cx,
cy,
midAngle,
innerRadius,
outerRadius,
startAngle,
endAngle,
fill,
payload,
percent,
value
} = props;
const sin = Math.sin(-RADIAN * midAngle);
const cos = Math.cos(-RADIAN * midAngle);
const sx = cx + (outerRadius + 5) * cos;
const sy = cy + (outerRadius + 5) * sin;
const mx = cx + (outerRadius + 10) * cos;
const my = cy + (outerRadius + 18) * sin;
const ex = mx + (cos >= 0 ? 1 : -1) * 20;
const ey = my;
const textAnchor = cos >= 0 ? "start" : "end";
const myCustomText = "abc"
return (
<g>
<text className="heavy" x={cx} y={cy} dy={8} textAnchor="middle" fill={fill}>
{myCustomText}
</text>
<Sector
cx={cx}
cy={cy}
innerRadius={innerRadius}
outerRadius={outerRadius}
startAngle={startAngle}
endAngle={endAngle}
fill={fill}
/>
<path
d={`M${sx},${sy}L${mx},${my}L${ex},${ey}`}
stroke={fill}
fill="none"
/>
<circle cx={ex} cy={ey} r={2} fill={fill} stroke="none" />
<text className="recharts-text recharts-label"
x={ex + (cos >= 0 ? 1 : -1) * 12}
y={ey}
textAnchor={textAnchor}
fill="#999"
dominantBaseline="central"
// fontSize={fontSize}
>
<tspan alignmentBaseline="middle">Del 400</tspan>
</text>
{/* <text
//style={{ fontWeight: "bold" }}
x={ex + (cos >= 0 ? 1 : -1) * 12}
y={ey}
textAnchor={textAnchor}
fill="#333"
>{`PV ${value}`}</text> */}
</g>
);
};
const OrderAcceptedChart = () => {
const [activeIndex, setActiveIndex] = useState(0);
const onPieEnter = useCallback(
(_: any, index: any) => {
setActiveIndex(index);
},
[setActiveIndex]
)
return (
<div className="chart rating">
<div className="cardInner">
<ResponsiveContainer width="100%" height={400}>
<PieChart style={myStyles}>
<Pie
activeIndex={activeIndex}
activeShape={renderActiveShape}
inactiveShape={renderActiveShape}
data={data}
dataKey="value"
nameKey="name"
cx="50%"
cy="50%"
innerRadius={60}
outerRadius={80}
fill="#8884d8"
paddingAngle={5}
labelLine={false}
// label
// cornerRadius={40}
>
{data.map((entry, index) => (
<Cell key={`cell-${index}`} fill={COLORS[index % COLORS.length]} />
))}
</Pie>
<Tooltip />
<Legend />
</PieChart>
</ResponsiveContainer>
</div>
</div>
);
};
export default OrderAcceptedChart;
Share image:
[1]: https://i.stack.imgur.com/7FIzq.png

