Newer
Older
import React, { useState, useEffect, useRef } from "react";
interface ChartData {
departement: string;
value: number;
}
const Pie_Chart = () => {
const originalData: ChartData[] = [
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
{ departement: "01", value: 21050 },
{ departement: "02", value: 45954 },
{ departement: "03", value: 21584 },
{ departement: "04", value: 53486 },
{ departement: "05", value: 87965 },
{ departement: "06", value: 34864 },
{ departement: "07", value: 48453 },
{ departement: "08", value: 87652 },
{ departement: "09", value: 12346 },
{ departement: "10", value: 78654 },
{ departement: "11", value: 48453 },
{ departement: "12", value: 78654 },
{ departement: "13", value: 28203 },
{ departement: "14", value: 21050 },
{ departement: "15", value: 45211 },
{ departement: "16", value: 87945 },
{ departement: "17", value: 47853 },
{ departement: "18", value: 75213 },
{ departement: "19", value: 21050 },
{ departement: "20", value: 78542 },
{ departement: "21", value: 21050 },
{ departement: "22", value: 78432 },
{ departement: "23", value: 21050 },
{ departement: "24", value: 21050 },
{ departement: "25", value: 27420 },
{ departement: "26", value: 27420 },
{ departement: "27", value: 27420 },
{ departement: "28", value: 27420 },
{ departement: "29", value: 75423 },
{ departement: "30", value: 21050 },
{ departement: "31", value: 78543 },
{ departement: "32", value: 21050 },
{ departement: "33", value: 100 },
{ departement: "34", value: 21050 },
{ departement: "35", value: 21050 },
{ departement: "36", value: 500 },
{ departement: "37", value: 24128 },
{ departement: "38", value: 24128 },
{ departement: "39", value: 2400 },
{ departement: "40", value: 24128 },
{ departement: "41", value: 7856 },
{ departement: "42", value: 2014 },
{ departement: "43", value: 3500 },
{ departement: "44", value: 24128 },
{ departement: "45", value: 2035 },
{ departement: "46", value: 150 },
{ departement: "47", value: 980 },
{ departement: "48", value: 748 },
{ departement: "49", value: 38806 },
{ departement: "50", value: 38806 },
{ departement: "51", value: 78543 },
{ departement: "52", value: 12999 },
{ departement: "53", value: 7865 },
{ departement: "54", value: 12999 },
{ departement: "55", value: 7854 },
{ departement: "56", value: 3698 },
{ departement: "57", value: 7412 },
{ departement: "58", value: 1236 },
{ departement: "59", value: 4789 },
{ departement: "60", value: 8963 },
{ departement: "61", value: 6321 },
{ departement: "62", value: 2145 },
{ departement: "63", value: 3256 },
{ departement: "64", value: 6589 },
{ departement: "65", value: 8965 },
{ departement: "66", value: 4587 },
{ departement: "67", value: 5697 },
{ departement: "68", value: 5413 },
{ departement: "69", value: 9713 },
{ departement: "70", value: 5418 },
{ departement: "71", value: 12999 },
{ departement: "72", value: 8642 },
{ departement: "73", value: 12999 },
{ departement: "74", value: 7319 },
{ departement: "75", value: 8246 },
{ departement: "76", value: 7853 },
{ departement: "77", value: 4687 },
{ departement: "78", value: 2480 },
{ departement: "79", value: 4283 },
{ departement: "80", value: 7352 },
{ departement: "81", value: 2052 },
{ departement: "82", value: 4052 },
{ departement: "83", value: 3058 },
{ departement: "84", value: 5602 },
{ departement: "85", value: 4206 },
{ departement: "86", value: 7069 },
{ departement: "87", value: 7605 },
{ departement: "88", value: 100 },
{ departement: "89", value: 200 },
{ departement: "90", value: 300 },
{ departement: "91", value: 400 },
{ departement: "92", value: 500 },
{ departement: "93", value: 600 },
{ departement: "94", value: 700 },
{ departement: "95", value: 800 },
{ departement: "971", value: 900 },
{ departement: "972", value: 1000 },
{ departement: "973", value: 1000 },
{ departement: "974", value: 1200 },
{ departement: "975", value: 1300 },
];
const chartRef = useRef<SVGSVGElement | null>(null);
const [numResults, setNumResults] = useState(10);
useEffect(() => {
const svg = d3.select(chartRef.current);
svg.selectAll("*").remove();
const margin = { top: 100, right: 10, bottom: 10, left: 10 };
const width = 400 - margin.left - margin.right;
const height = 400 - margin.top - margin.bottom;
const radius = Math.min(width, height) / 2;
const sortedData = [...originalData].sort((a, b) => b.value - a.value);
const displayedData = sortedData.slice(0, numResults);
const totalSales = d3.sum(sortedData, (d) => d.value);
const otherData = {
departement: "Autres",
value: totalSales - d3.sum(displayedData, (d) => d.value),
};
const pie = d3.pie()
.value((d) => d.value);
const arc = d3.arc()
.outerRadius(radius)
const colorScale = d3.scaleOrdinal(d3.schemeCategory10);
const g = svg.append("g")
.attr("transform", `translate(${width / 2},${height / 2})`);
const arcs = g.selectAll("arc")
.data(pie([...displayedData, otherData]))
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
.attr("class", "arc");
arcs.append("path")
.attr("d", arc)
.attr("fill", (d) => (d.data.departement === "Autres" ? "gray" : colorScale(d.data.departement)));
const outerArc = d3.arc()
.innerRadius(radius * 0.9)
.outerRadius(radius * 0.9);
arcs.append("polyline")
.attr("stroke", "black")
.attr("stroke-width", 1)
.attr("fill", "none")
.attr("points", (d) => {
const posA = arc.centroid(d);
const posB = outerArc.centroid(d);
const posC = outerArc.centroid(d);
const midangle = d.startAngle + (d.endAngle - d.startAngle) / 2;
posC[0] = radius * 0.95 * (midangle < Math.PI ? 1 : -1);
return [posA, posB, posC];
});
arcs.append("text")
.attr("transform", (d) => `translate(${outerArc.centroid(d)})`)
.style("text-anchor", "middle")
.text((d) => {
const percentage = (d.data.value / totalSales) * 100;
return `${d.data.departement}: ${percentage.toFixed(2)}%`;
});
<div>
<label>
Nombre de résultats à afficher :
<input
type="number"
value={numResults}
onChange={(e) => setNumResults(parseInt(e.target.value, 10))}
/>
</label>
<div style={{textAlign: "center"}}>
<svg id="donut-chart" width={400} height={400} ref={chartRef}
style={{display: "block", margin: "0 auto"}}></svg>
</div>
</div>