cs-2022-class-profile/components/PieChart.tsx

89 lines
2.2 KiB
TypeScript
Raw Normal View History

import { Group } from "@visx/group";
import Pie, { ProvidedProps } from "@visx/shape/lib/shapes/Pie";
2022-06-18 22:50:08 -04:00
import React from "react";
import styles from "./PieChart.module.css";
interface PieChartProps {
data: PieChartData[];
width: number;
2022-06-18 22:55:05 -04:00
labelWidth: number;
2022-07-06 19:44:48 -04:00
padRadius?: number;
innerRadius?: number;
className?: string;
}
interface PieChartData {
category: string;
value: number;
}
2022-07-06 19:44:48 -04:00
export function PieChart({
width,
labelWidth,
padRadius = width * 0.35,
innerRadius = width * 0.015,
...props
}: PieChartProps) {
2022-06-18 22:55:05 -04:00
const pieWidth = width * 0.5 - labelWidth;
return (
2022-06-18 22:35:39 -04:00
<svg className={props.className} width={width} height={width}>
<Group top={width * 0.5} left={width * 0.5}>
<Pie
data={props.data}
fill="aqua"
pieValue={(d: PieChartData) => d.value}
2022-06-18 22:35:39 -04:00
cornerRadius={10}
padAngle={0.075}
2022-07-06 19:44:48 -04:00
padRadius={padRadius}
innerRadius={innerRadius}
2022-06-18 22:35:39 -04:00
outerRadius={pieWidth}
>
2022-06-18 22:35:39 -04:00
{(pie) => <PieSlices {...pie} isLabel={false} />}
</Pie>
<Pie
data={props.data}
fill="rgb(37, 45, 65)"
pieValue={(d: PieChartData) => d.value}
innerRadius={pieWidth}
outerRadius={width * 0.5}
>
{(pie) => <PieSlices {...pie} isLabel={true} />}
</Pie>
</Group>
</svg>
);
}
2022-06-18 22:35:39 -04:00
type PieSlicesProps<PieChartData> = ProvidedProps<PieChartData> & {
isLabel: boolean;
};
2022-06-18 22:35:39 -04:00
export function PieSlices({ isLabel, ...props }: PieSlicesProps<PieChartData>) {
return (
<>
{props.arcs.map((arc) => {
const [centroidX, centroidY] = props.path.centroid(arc);
2022-06-18 22:50:08 -04:00
const pathArc = props.path(arc) as string;
2022-06-18 22:35:39 -04:00
return (
<g className={styles.group} key={`arc-${arc.data.category}`}>
<path
className={isLabel ? styles.labelPath : styles.piePath}
d={pathArc}
/>
<text
className={isLabel ? styles.labelText : styles.pieText}
x={centroidX}
y={centroidY}
textAnchor="middle"
>
{isLabel ? `${arc.data.category}` : `${arc.data.value}%`}
</text>
</g>
);
})}
</>
);
}