-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathScatterChart.tsx
More file actions
104 lines (95 loc) · 3.19 KB
/
Copy pathScatterChart.tsx
File metadata and controls
104 lines (95 loc) · 3.19 KB
1
2
3
4
5
6
7
8
9
10
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
import React from "react";
import { Scatter } from "react-chartjs-2";
import { Chart as ChartJS, LinearScale, PointElement, LineElement, Tooltip, Legend } from "chart.js";
import { getDistributedColor } from "@/functions/Colors";
ChartJS.register(LinearScale, PointElement, LineElement, Tooltip, Legend);
export interface ScatterDataSet {
label: string;
data: { x: number; y: number }[];
color?: string;
}
export interface ScatterChartProps {
datasets: ScatterDataSet[];
xLabel?: string;
yLabel?: string;
showDiagonal?: boolean;
}
const ScatterChart: React.FC<ScatterChartProps> = ({ datasets, xLabel, yLabel, showDiagonal }) => {
if (datasets.length === 0) return null;
const maxVal = Math.max(...datasets.flatMap((ds) => ds.data.flatMap((p) => [Math.abs(p.x), Math.abs(p.y)])), 0);
const chartDatasets = datasets.map((ds, idx) => ({
label: ds.label,
data: ds.data,
backgroundColor: ds.color ?? getDistributedColor(idx, datasets.length),
}));
if (showDiagonal) {
const diagonalBase = {
backgroundColor: "transparent",
showLine: true,
borderColor: "#aaa",
borderDash: [6, 4],
pointRadius: 0,
borderWidth: 1,
};
chartDatasets.unshift(
{
...diagonalBase,
label: "x = y",
data: [
{ x: 0, y: 0 },
{ x: maxVal, y: maxVal },
],
} as any,
{
...diagonalBase,
label: "+10%",
borderDash: [3, 3],
borderWidth: 0.5,
data: [
{ x: 0, y: 0 },
{ x: maxVal, y: maxVal * 1.1 },
],
} as any,
{
...diagonalBase,
label: "−10%",
borderDash: [3, 3],
borderWidth: 0.5,
data: [
{ x: 0, y: 0 },
{ x: maxVal, y: maxVal * 0.9 },
],
} as any
);
}
return (
<Scatter
data={{ datasets: chartDatasets }}
options={{
responsive: true,
aspectRatio: 1.5,
plugins: {
legend: {
position: "right",
labels: {
boxWidth: 10,
font: { size: 11 },
filter: (item) => !["x = y", "+10%", "−10%"].includes(item.text ?? ""),
},
},
tooltip: {
callbacks: {
label: (ctx) =>
`${ctx.dataset.label}: (${ctx.parsed.x?.toFixed(4)}, ${ctx.parsed.y?.toFixed(4)})`,
},
},
},
scales: {
x: { min: 0, title: { display: true, text: xLabel ?? "" } },
y: { min: 0, title: { display: true, text: yLabel ?? "" } },
},
}}
/>
);
};
export default ScatterChart;