I am using Recharts to create a simple pie chart. My issue likely stems from the fact the entire thing is SVG-based. I would like to have a selected pie slice change color (both fill and stroke). So I do the following:
import { useState } from 'react';
import { Sector, Pie, PieChart, ResponsiveContainer } from 'recharts';
export function SinglePie({ data }) {
const [selectedCellLabel, setHighlightedCell] = useState(undefined);
const onm ouseEnter = (event) => setHighlightedCell(event.payload.payload.label);
const onm ouseLeave = () => setHighlightedCell(undefined);
function renderActiveShape(props) {
return <Sector {...props} fill="#CFBCF7" stroke="#7C53E4" />;
}
return (
<ResponsiveContainer width="100%" height="100%">
<PieChart>
<Pie
data={data}
activeIndex={data.findIndex((datum) => datum.label === selectedCellLabel)}
activeShape={renderActiveShape}
dataKey={ChartDataKeys.VALUE}
nameKey={ChartDataKeys.LABEL}
fill="#CEF1EE"
stroke="#64E0D5"
onm ouseEnter={onMouseEnter}
onm ouseLeave={onMouseLeave}
/>
</PieChart>
</ResponsiveContainer>
);
}
Then render with:
<div style={{ width: 250, height: 250 }}>
<SinglePie data={[
{
label: 'First Slice',
value: 4,
},
{
label: 'Second Slice',
value: 6,
},
{
label: 'Third Slice',
value: 2,
},
]} />
</div>
And unfortunately, on hovering the First Slice, what I see is this:
However, hovering the Third Slice looks ok:
You can see the difference between stroke width in the two cases. this is because the SVG slices overlap each other.
I know that SVG rendering is based on order, and adding a z
prop won't help. But what will?
I would like to be able to see all slices with their strokes, as is required by my UI designer:
CodePudding user response:
You can use .raise()
function of d3 library.
First, you need to add <script src="https://d3js.org/d3.v7.min.js"></script>
tag to your index.html
.
And then you can move the selected slice to last in your onMouseEnter
function like this:
const onm ouseEnter = (event) => {
setHighlightedCell(event.payload.payload.label);
const selectedIndex = data.findIndex(
(datum) => datum.label === event.payload.payload.label
);
if (selectedIndex > -1) {
const gListItem = d3.select(
`.recharts-pie-sector:has(path[name="${event.payload.payload.label}"])`
);
gListItem.raise();
}
};
You can take a look at this stackblitz for a live working example of this solution.