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; // console.log(data); return data.length == 0 ? : ( b.categoryCode - a.categoryCode} outerRadius={radius} cornerRadius={0} > {(pie) => ( c.data.categoryName} onClickDatum={({ data: category }) => console.log('clicked: ', category.categoryName) } getColor={(arc) => { return arc.data.categoryColor; }} /> )} ); } // 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.categoryForeground; } }