Files
TechRadarAJR/src/components/Chart/RadarChart.tsx
2022-09-13 11:28:06 +02:00

110 lines
2.8 KiB
TypeScript

import * as d3 from "d3";
import React from "react";
import ReactTooltip from "react-tooltip";
import { ConfigData } from "../../config";
import { Item } from "../../model";
import { XAxis, YAxis } from "./Axes";
import BlipPoints from "./BlipPoints";
import QuadrantRings from "./QuadrantRings";
import "./chart.scss";
const RingLabel: React.FC<{
ring: string;
xScale: d3.ScaleLinear<number, number>;
yScale: d3.ScaleLinear<number, number>;
config: ConfigData;
}> = ({ ring, xScale, yScale, config }) => {
const ringIndex = config.rings.findIndex((r) => r === ring);
const ringRadius = config.chartConfig.ringsAttributes[ringIndex].radius,
previousRingRadius =
ringIndex === 0
? 0
: config.chartConfig.ringsAttributes[ringIndex - 1].radius,
// middle point in between two ring arcs
distanceFromCentre =
previousRingRadius + (ringRadius - previousRingRadius) / 2;
return (
<g className="ring-label">
{/* Right hand-side label */}
<text
x={xScale(distanceFromCentre)}
y={yScale(0)}
textAnchor="middle"
dy=".35em"
>
{ring}
</text>
{/* Left hand-side label */}
<text
x={xScale(-distanceFromCentre)}
y={yScale(0)}
textAnchor="middle"
dy=".35em"
>
{ring}
</text>
</g>
);
};
const RadarChart: React.FC<{
items: Item[];
config: ConfigData;
}> = ({ items, config }) => {
const xScale = d3
.scaleLinear()
.domain(config.chartConfig.scale)
.range([0, config.chartConfig.size]);
const yScale = d3
.scaleLinear()
.domain(config.chartConfig.scale)
.range([config.chartConfig.size, 0]);
return (
<div className="chart" style={{ maxWidth: `${config.chartConfig.size}px` }}>
<svg
viewBox={`0 0 ${config.chartConfig.size} ${config.chartConfig.size}`}
>
<g transform={`translate(${xScale(0)}, 0)`}>
<YAxis scale={yScale} />
</g>
<g transform={`translate(0, ${yScale(0)})`}>
<XAxis scale={xScale} />
</g>
{Object.values(config.quadrantsMap).map((value, index) => (
<QuadrantRings
key={index}
quadrant={value}
xScale={xScale}
config={config}
/>
))}
{Array.from(config.rings).map((ring: string, index) => (
<RingLabel
key={index}
ring={ring}
xScale={xScale}
yScale={yScale}
config={config}
/>
))}
<BlipPoints
items={items}
xScale={xScale}
yScale={yScale}
config={config}
/>
</svg>
<ReactTooltip className="tooltip" offset={{ top: -5 }} />
</div>
);
};
export default RadarChart;