-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathRadarChart.tsx
152 lines (133 loc) · 4.48 KB
/
RadarChart.tsx
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
import Sketch from "react-p5";
import p5Types from "p5"; //Typen von p5
interface RadarChartValue {
name: string;
value: number;
}
//Demodaten
const values: RadarChartValue[] = [
{
name: "Mathe",
value: 5,
},
{
name: "Sport",
value: 9,
},
{
name: "Statistik",
value: 8,
},
{
name: "Physik",
value: 10,
},
{
name: "Französisch",
value: 6,
},
{
name: "Musik",
value: 2,
},
{
name: "Biologie",
value: 4,
},
{
name: "Englisch",
value: 9,
},
];
function RadarChart() {
/* Eingabewerte, um den Code clean zu halten*/
const padding = 100; // Der Abstand innterhalb des Canvases der dafür sorgt, dass der Text nicht abgeschnitten ist
const canvasSize = 700; // Die Größe der Zeichenfläche in px
const numberOfElements = values.length; // Die Anzahl der Unterschiedlichen Dimensionen
const numberOfPossibleSelections = 10; // Die Anzahl unterschiedlicher Wertungen
/* Berechnung einiger Konstanten, die wir brauchen */
const center = canvasSize / 2; // Die Mitte der Zeichenfläche
const spiderRadius = canvasSize / 2 - padding; // Die Länge der Linien, die nach außen gehen
const spaceBetweenCircles = spiderRadius / numberOfPossibleSelections; // Der Abstand zwischen den Ringen
const singleElementAngle = 360 / numberOfElements; // Der Winkel der Dimensionen
/* Helper-Methode, um den Text optimal auszurichten*/
function setTextAlignBasedOnAngle(p5: p5Types, angle: number) {
if (angle >= -10 && angle < 10) {
p5.textAlign(p5.LEFT, p5.CENTER);
} else if (angle >= 10 && angle < 80) {
p5.textAlign(p5.LEFT, p5.TOP);
} else if (angle >= 80 && angle < 100) {
p5.textAlign(p5.CENTER, p5.TOP);
} else if (angle >= 100 && angle < 170) {
p5.textAlign(p5.RIGHT, p5.TOP);
} else if (angle >= 170 && angle < 190) {
p5.textAlign(p5.RIGHT, p5.CENTER);
} else if (angle >= 190 && angle < 260) {
p5.textAlign(p5.RIGHT, p5.BOTTOM);
} else if (angle >= 260 && angle < 280) {
p5.textAlign(p5.CENTER, p5.BOTTOM);
} else if (angle >= 280 && angle < 350) {
p5.textAlign(p5.LEFT, p5.BOTTOM);
} else {
p5.textAlign(p5.CENTER, p5.CENTER);
}
}
/* Setup Methode */
const setup = (p5: p5Types, canvasParentRef: Element) => {
p5.createCanvas(canvasSize, canvasSize).parent(canvasParentRef);
p5.angleMode("degrees");
p5.textSize(14);
};
/* Sich wiederholdende draw Methode */
const draw = (p5: p5Types) => {
p5.background(255);
/* Ringe im Hintergrund */
p5.strokeWeight(3);
p5.stroke(230);
for (let circle = 1; circle <= numberOfPossibleSelections; circle++) {
p5.noFill();
p5.ellipse(
center,
center,
spaceBetweenCircles * circle * 2,
spaceBetweenCircles * circle * 2
);
}
/* Spinnennetz */
p5.stroke(200);
p5.strokeWeight(4);
for (let i = 0; i < numberOfElements; i++) {
p5.strokeWeight(4);
var angle = singleElementAngle * i;
var dx = spiderRadius * p5.cos(angle);
var dy = spiderRadius * p5.sin(angle);
p5.line(center, center, center + dx, center + dy);
}
/* Texte */
p5.strokeWeight(0);
p5.fill(0);
for (let i = 0; i < numberOfElements; i++) {
const textAngle = singleElementAngle * i;
dx = (spiderRadius + 20) * p5.cos(textAngle);
dy = (spiderRadius + 20) * p5.sin(textAngle);
setTextAlignBasedOnAngle(p5, textAngle);
p5.text(values[i].name, center + dx, center + dy);
}
/* Vektor und Datenpunkte*/
p5.strokeWeight(4);
p5.stroke("#ee7900");
p5.fill(228, 121, 0, 100);
p5.beginShape();
for (var pointIndex = 0; pointIndex < values.length; pointIndex++) {
const pointAngle = singleElementAngle * pointIndex; // Berechnet den Winkel der jeweiligen Dimension
const radiusForPoint = spaceBetweenCircles * values[pointIndex].value;
const dxPoint = radiusForPoint * p5.cos(pointAngle);
const dyPoint = radiusForPoint * p5.sin(pointAngle);
p5.vertex(center + dxPoint, center + dyPoint);
p5.ellipse(center + dxPoint, center + dyPoint, 7, 7); // Da wir die Koordinaten des Datenpunktes hier schon berechnet haben können wir an diesen direkt den Punkt zeichnen
}
p5.endShape(p5.CLOSE);
};
return <Sketch setup={setup} draw={draw} />;
}
export { RadarChart };