Custom Active Shape Rendering in React
In this snippet, I implement a custom renderActiveShape function using React to display dynamic shapes based on data. It calculates coordinates for drawing shapes and includes text annotations to indicate conversion rates. This is perfect for dynamic charting applications!Yash
javascript
14 days ago
4.1 kB
4
Indexable
const renderActiveShape = (props) => { const RADIAN = Math.PI / 180; const { cx, cy, midAngle, innerRadius, outerRadius, startAngle, endAngle, fill, payload, percent } = props; const sin = Math.sin(-RADIAN * midAngle); const cos = Math.cos(-RADIAN * midAngle); const sx = cx + (outerRadius + 10) * cos; const sy = cy + (outerRadius + 10) * sin; const mx = cx + (outerRadius + 30) * cos; const my = cy + (outerRadius + 30) * sin; const ex = mx + (cos >= 0 ? 1 : -1) * 22; const ey = my; const textAnchor = cos >= 0 ? 'start' : 'end'; const conversionRate = `(${payload.convertedLeadCount}/${payload.leadCount}) `+((payload.convertedLeadCount / payload.leadCount) * 100).toFixed(1); return ( <g> <text x={cx} y={cy} dy={8} textAnchor="middle" fill={fill}> {payload.name} </text> <Sector cx={cx} cy={cy} innerRadius={innerRadius} outerRadius={outerRadius} startAngle={startAngle} endAngle={endAngle} fill={fill} /> <Sector cx={cx} cy={cy} startAngle={startAngle} endAngle={endAngle} innerRadius={outerRadius + 6} outerRadius={outerRadius + 10} 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 x={ex + (cos >= 0 ? 1 : -1) * 12} y={ey} textAnchor={textAnchor} fill="#333">{`Leads ${payload.leadCount}`}</text> <text x={ex + (cos >= 0 ? 1 : -1) * 12} y={ey} dy={18} textAnchor={textAnchor} fill="#999"> {`${conversionRate}%`} </text> </g> ); }; export const LeadSourceBreakdown = ({ dashBoardData, heading, dataKey, w }) => { const [activeIndex, setActiveIndex] = useState(0); const pieColors = useMemo(() => { return generateColors(size(dashBoardData?.[dataKey])); }, [dashBoardData, dataKey]); const filteredData = useMemo(() => { const withoutZero = filter(dashBoardData?.[dataKey], (d) => d.leadCount !== 0); const withZero = filter(dashBoardData?.[dataKey], (d) => d.leadCount === 0); return { withoutZero, withZero }; }, [dashBoardData, dataKey]); const onPieEnter = (_, index) => { setActiveIndex(index); }; return ( <Box w={w ?? '40%'}> <Box p={4} bg="white" shadow="md" borderRadius="lg" flex="1" minW="550px" maxH="450px" > <Text fontSize="md" fontWeight="semibold" mb={4} color="#333"> {heading} </Text> <ResponsiveContainer width="100%" height={300}> <PieChart> <Pie activeIndex={activeIndex} activeShape={renderActiveShape} data={filteredData?.withoutZero || []} dataKey="leadCount" nameKey="name" cx="50%" cy="50%" innerRadius={70} outerRadius={90} fill="#8884d8" paddingAngle={5} onMouseEnter={onPieEnter} > {filteredData?.withoutZero?.map((entry, index) => ( <Cell key={`cell-${index}`} fill={pieColors[index]} /> ))} </Pie> </PieChart> </ResponsiveContainer> </Box> </Box> ); };
Editor is loading...
Leave a Comment