import React, { useState } from 'react';
import Pie, { ProvidedProps, PieArcDatum } from '@visx/shape/lib/shapes/Pie';
import { scaleOrdinal } from '@visx/scale';
import { Group } from '@visx/group';
import { animated, useTransition, interpolate } from '@react-spring/web';
import LoadingSpinner from '@/components/ui/spinner';
// accessor functions
const frequency = (c) => c.percentage;
const defaultMargin = { top: 20, right: 20, bottom: 20, left: 20 };
export type PieProps = {
data: any
width: number;
height: number;
margin?: typeof defaultMargin;
animate?: boolean;
};
export default function PieChart({
data,
width,
height,
margin = defaultMargin,
animate = true,
}: PieProps) {
if (width < 10) return null;
const innerWidth = width - margin.left - margin.right;
const innerHeight = height - margin.top - margin.bottom;
const radius = Math.min(innerWidth, innerHeight) / 2;
const centerY = innerHeight / 2;
const centerX = innerWidth / 2;
return data.length == 0 ? : (
);
}
// react-spring transition definitions
type AnimatedStyles = { startAngle: number; endAngle: number; opacity: number };
const fromLeaveTransition = ({ endAngle }: PieArcDatum) => ({
// enter from 360° if end angle is > 180°
startAngle: endAngle > Math.PI ? 2 * Math.PI : 0,
endAngle: endAngle > Math.PI ? 2 * Math.PI : 0,
opacity: 0,
});
const enterUpdateTransition = ({ startAngle, endAngle }: PieArcDatum) => ({
startAngle,
endAngle,
opacity: 1,
});
type AnimatedPieProps = ProvidedProps & {
animate?: boolean;
getKey: (d: PieArcDatum) => string;
getColor: (d: PieArcDatum) => string;
onClickDatum: (d: PieArcDatum) => void;
delay?: number;
};
function AnimatedPie({
animate,
arcs,
path,
getKey,
getColor,
onClickDatum,
}: AnimatedPieProps) {
const transitions = useTransition, AnimatedStyles>(arcs, {
from: animate ? fromLeaveTransition : enterUpdateTransition,
enter: enterUpdateTransition,
update: enterUpdateTransition,
leave: animate ? fromLeaveTransition : enterUpdateTransition,
keys: getKey,
});
return transitions((props, arc, { key }) => {
const [centroidX, centroidY] = path.centroid(arc);
const hasSpaceForLabel = arc.endAngle - arc.startAngle >= 0.1;
return (
path({
...arc,
startAngle,
endAngle,
}),
)}
fill={getColor(arc)}
onClick={() => onClickDatum(arc)}
onTouchStart={() => onClickDatum(arc)}
/>
{hasSpaceForLabel && false && (
{getKey(arc)}
)}
);
});
function getForeground(arc: PieArcDatum) {
return arc.data.foreground;
}
}