Files
TechRadarAJR/src/components/Chart/QuadrantRings.tsx
2023-06-01 16:49:41 +02:00

93 lines
2.4 KiB
TypeScript

import * as d3 from "d3";
import React from "react";
import { ConfigData } from "../../config";
import { QuadrantConfig } from "../../model";
const arcAngel = [
[(3 * Math.PI) / 2, (4 * Math.PI) / 2],
[0, Math.PI / 2],
[Math.PI, (Math.PI * 3) / 2],
[Math.PI / 2, Math.PI],
];
function arcPath(
quadrantPosition: number,
ringPosition: number,
xScale: d3.ScaleLinear<number, number>,
config: ConfigData
) {
const [startAngle, endAngle] = arcAngel[quadrantPosition - 1];
const arcAttrs = config.chartConfig.ringsAttributes[ringPosition],
ringRadiusPx = xScale(arcAttrs.radius) - xScale(0),
arc = d3.arc();
return (
arc({
innerRadius: ringRadiusPx - arcAttrs.arcWidth,
outerRadius: ringRadiusPx,
startAngle,
endAngle,
}) || undefined
);
}
const QuadrantRings: React.FC<{
quadrant: QuadrantConfig;
xScale: d3.ScaleLinear<number, number>;
config: ConfigData;
}> = ({ quadrant, xScale, config }) => {
// order from top-right clockwise
const gradientAttributes = [
{ x: 0, y: 0, cx: 1, cy: 1, r: 1 },
{ x: xScale(0), y: 0, cx: 0, cy: 1, r: 1 },
{ x: 0, y: xScale(0), cx: 1, cy: 0, r: 1 },
{ x: xScale(0), y: xScale(0), cx: 0, cy: 0, r: 1 },
];
const gradientId = `${quadrant.position}-radial-gradient`,
quadrantSize = config.chartConfig.size / 2;
return (
<g className="quadrant-ring">
{/* Definition of the quadrant gradient */}
<defs>
<radialGradient
id={gradientId}
{...gradientAttributes[quadrant.position - 1]}
>
<stop offset="0%" stopColor={quadrant.colour}></stop>
<stop
offset="100%"
stopColor={quadrant.colour}
stopOpacity="0"
></stop>
</radialGradient>
</defs>
{/* Gradient background area */}
<rect
width={quadrantSize}
height={quadrantSize}
x={gradientAttributes[quadrant.position - 1].x}
y={gradientAttributes[quadrant.position - 1].y}
fill={`url(#${gradientId})`}
style={{ opacity: 0.5 }}
/>
{/* Rings' arcs */}
{Array.from(config.rings).map((ringPosition, index) => (
<path
key={index}
fill={quadrant.colour}
d={arcPath(quadrant.position, index, xScale, config)}
style={{
transform: `translate(${quadrantSize}px, ${quadrantSize}px)`,
}}
/>
))}
</g>
);
};
export default QuadrantRings;