Newer
Older
import React, { useEffect, useRef } from "react";
import * as d3 from "d3";
export default function DonutChart({ data }) {
const ref = useRef();
const svgWidth = 600;
const svgHeight = 600;
const width = 400;
const height = 400;
const radius = Math.min(width, height) / 2;
const innerRadius = radius * 0.6;
const outerRadius = radius * 0.9;
const hoverOuterRadius = outerRadius + 20;
useEffect(() => {
if (!data || data.length === 0) {
return;
}
const totalOccurrences = data.reduce((acc, item) => acc + item.occurrences, 0);
const minPercentage = 1;
let otherData = { region: "Autres", occurrences: 0, details: [] };
let newData = data.filter(d => {
let percentage = (d.occurrences / totalOccurrences) * 100;
if (percentage < minPercentage) {
otherData.occurrences += d.occurrences;
otherData.details.push(`${d.region} (${percentage.toFixed(2)}%)`);
return false;
}
return true;
});
if (otherData.occurrences > 0) {
newData.push(otherData);
}
const pieData = d3.pie().value(d => d.occurrences)(newData);
const arc = d3.arc().innerRadius(innerRadius).outerRadius(outerRadius);
const hoverArc = d3.arc().innerRadius(innerRadius).outerRadius(hoverOuterRadius);
const svg = d3.select(ref.current)
.attr("width", svgWidth)
.attr("height", svgHeight)
.append("g")
.attr("transform", `translate(${svgWidth / 2}, ${svgHeight / 2})`);
svg.selectAll("path")
.data(pieData)
.enter()
.append("path")
.attr("d", arc)
.attr("fill", (d, i) => d3.schemeCategory10[i % 10])
.on("mouseover", function(event, d) {
d3.select(this).transition().attr("d", hoverArc);
if (d.data.region === "Autres") {
svg.append("text")
.attr("class", "details-text")
.attr("x", 0)
.attr("y", 0)
.attr("text-anchor", "middle")
.selectAll("tspan")
.data(otherData.details)
.enter()
.append("tspan")
.attr("x", 0)
.attr("dy", "1.2em")
.text(detail => detail);
} else {
const percentage = ((d.data.occurrences / totalOccurrences) * 100).toFixed(2);
const text = `${d.data.region}: ${percentage}%`;
svg.append("text")
.attr("class", "tooltip")
.attr("x", 0)
.attr("y", 20)
.attr("text-anchor", "middle")
.text(text);
}
})
.on("mouseout", function() {
d3.select(this).transition().attr("d", arc);
svg.selectAll(".details-text").remove();
svg.selectAll(".tooltip").remove();
});
return <svg ref={ref}></svg>;