summaryrefslogtreecommitdiff
path: root/old_stuff/src/components/RadarChart.astro
diff options
context:
space:
mode:
Diffstat (limited to 'old_stuff/src/components/RadarChart.astro')
-rw-r--r--old_stuff/src/components/RadarChart.astro132
1 files changed, 132 insertions, 0 deletions
diff --git a/old_stuff/src/components/RadarChart.astro b/old_stuff/src/components/RadarChart.astro
new file mode 100644
index 0000000..0a3d434
--- /dev/null
+++ b/old_stuff/src/components/RadarChart.astro
@@ -0,0 +1,132 @@
+---
+import "@styles/terminal.css"
+
+interface Entry {
+ name: string;
+ weight: number;
+}
+
+interface Props {
+ max: number
+ data: Entry[];
+}
+
+const { max, data } = Astro.props
+
+const chartPadding = 100;
+const chartSize = 400;
+const chartCenter = chartSize / 2;
+
+const chartData = data ;// .sort((a, b) => b.weight - a.weight).slice(0, data.length);
+const pointPadding = 0;
+const rings = [...Array(6).keys()];
+
+const getX = (angle: number, value: number) =>
+ Math.cos(angle - Math.PI / 2) * value;
+const getY = (angle: number, value: number) =>
+ Math.sin(angle - Math.PI / 2) * value;
+
+const axes = chartData.map((_, index) => {
+ const angle = (Math.PI * 2 * index) / chartData.length;
+ const x = getX(angle, chartSize / 2);
+ const y = getY(angle, chartSize / 2);
+ const points = [
+ [0, 0],
+ [x, y],
+ ]
+ .map((point) => point[0] + "," + point[1])
+ .join(" ");
+ return {
+ points: points,
+ };
+});
+
+const properties = chartData.map((item, index) => {
+ const { name, weight: total } = item;
+ const clamp = Number(total / (max + pointPadding));
+ const angle = (Math.PI * 2 * index) / chartData.length;
+ const x = getX(angle, (clamp * chartSize) / 2);
+ const y = getY(angle, (clamp * chartSize) / 2);
+ return { name: name, total: total, x: x, y: y };
+});
+
+const shape =
+ properties.reduce((items, item, index) => {
+ const { x, y } = item;
+ const string = `${index === 0 ? "M" : "L"}${x},${y}`;
+ return items + string;
+ }, "") + "z";
+
+const strokeColor = "stroke-[var(--alt)]";
+const shapeClass = "stroke-[var(--primary)] fill-[#7ed4fb]/50";
+
+---
+ <div class="w-full grid md:grid-cols-1 items-center gap-16 p-0">
+ <svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox={`-${chartPadding / 2} -${chartPadding / 2} ${chartSize + chartPadding} ${chartSize + chartPadding}`}
+ role="presentation"
+ >
+ <g transform={`translate(${chartCenter},${chartCenter})`}>
+ {
+ rings.map((_, index) => {
+ return (
+ <circle
+ cx={0}
+ cy={0}
+ r={
+ ((index / rings.length) * chartSize) /
+ Number((Math.PI / 2 + 0.1).toFixed(2))
+ }
+ class={strokeColor}
+ fill="none"
+ stroke-width={1}
+ />
+ );
+ })
+ }
+ {
+ axes.map((axis) => {
+ const { points } = axis;
+ return (
+ <polyline
+ points={points}
+ class={strokeColor}
+ fill="none"
+ stroke-width={1}
+ />
+ );
+ })
+ }
+ <path d={shape} class=`${shapeClass}` stroke-width={1.5}></path>
+ {
+ properties.map((property, index) => {
+ const length = 1.1;
+ const angle = (Math.PI * 2) * index / chartData.length;
+ const maxX = getX(angle, (length * chartSize) / 2);
+ const maxY = getY(angle, (length * chartSize) / 2);
+ let textAngle = (angle * (180 / Math.PI))
+ if (90 < textAngle && textAngle < 270) {
+ textAngle += 180
+ }
+ return (
+ <g transform={`translate(${maxX},${maxY})`}>
+ <text
+ x={0}
+ y={0}
+ fill="var(--secondary)"
+ font-size="2rem"
+ font-weight="bold"
+ text-anchor="middle"
+ transform=`rotate(${textAngle})`
+ dominant-baseline="middle"
+ >
+ {property.name}
+ </text>
+ </g>
+ );
+ })
+ }
+ </g>
+ </svg>
+ </div>