Skip to content

Commit bb3c487

Browse files
author
tonyliuzj
committed
Update animation
1 parent a27fd18 commit bb3c487

2 files changed

Lines changed: 48 additions & 65 deletions

File tree

src/components/AdaptiveChart.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -180,13 +180,13 @@ export default function AdaptiveChart({ value, label, subLabel, color, compact =
180180
// Default: Circle Design
181181
return (
182182
<CircleChart
183-
value={visualValue}
183+
value={chartValue}
184184
label={label}
185185
subLabel={subLabel}
186186
color={color}
187187
compact={compact}
188-
displayValue={chartValue}
189-
animationDuration={animate ? 0 : 800}
188+
displayValue={visualValue}
189+
animationDuration={animate ? 800 : 0}
190190
/>
191191
);
192192
}

src/components/CircleChart.tsx

Lines changed: 45 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
"use client";
22

33
import React from "react";
4-
import { RadialBarChart, RadialBar, PolarAngleAxis, ResponsiveContainer } from "recharts";
54
import { useTheme } from "@/contexts/ThemeContext";
65

76
interface CircleChartProps {
@@ -55,46 +54,56 @@ export default function CircleChart({
5554

5655
const fillColor = getThemeColor();
5756

58-
const data = [
59-
{
60-
name: label,
61-
value: chartValue,
62-
fill: fillColor,
63-
},
64-
];
57+
const renderSVG = (strokeWidth: number) => {
58+
// 50 is center (cx, cy), so max radius is 50. We subtract half of strokeWidth to stay inside.
59+
const radius = 50 - strokeWidth / 2;
60+
const circumference = 2 * Math.PI * radius;
61+
const strokeDashoffset = circumference - (chartValue / 100) * circumference;
62+
63+
// Fallback animation duration if needed
64+
const duration = animationDuration > 0 ? animationDuration : 0;
65+
const transitionStyle = duration > 0
66+
? { transition: `stroke-dashoffset ${duration}ms ease-out, stroke ${duration}ms ease-out` }
67+
: {};
68+
69+
return (
70+
<svg
71+
viewBox="0 0 100 100"
72+
className="w-full h-full transform -rotate-90 overflow-visible"
73+
>
74+
{/* Background Track */}
75+
<circle
76+
cx="50"
77+
cy="50"
78+
r={radius}
79+
fill="transparent"
80+
stroke="currentColor"
81+
strokeWidth={strokeWidth}
82+
className="text-muted/20"
83+
/>
84+
{/* Progress Arc */}
85+
<circle
86+
cx="50"
87+
cy="50"
88+
r={radius}
89+
fill="transparent"
90+
stroke={fillColor}
91+
strokeWidth={strokeWidth}
92+
strokeDasharray={circumference}
93+
strokeDashoffset={strokeDashoffset}
94+
strokeLinecap="round"
95+
style={transitionStyle}
96+
/>
97+
</svg>
98+
);
99+
};
65100

66101
// Compact mode for table views
67102
if (compact) {
68103
return (
69104
<div className="flex items-center justify-center">
70105
<div className="h-[40px] w-[40px] relative">
71-
<ResponsiveContainer width="100%" height="100%">
72-
<RadialBarChart
73-
cx="50%"
74-
cy="50%"
75-
innerRadius="65%"
76-
outerRadius="95%"
77-
barSize={7}
78-
data={data}
79-
startAngle={90}
80-
endAngle={-270}
81-
>
82-
<PolarAngleAxis
83-
type="number"
84-
domain={[0, 100]}
85-
angleAxisId={0}
86-
tick={false}
87-
/>
88-
<RadialBar
89-
background={{ fill: 'rgba(128, 128, 128, 0.1)' }}
90-
dataKey="value"
91-
cornerRadius={10}
92-
animationDuration={animationDuration}
93-
animationEasing="ease-out"
94-
/>
95-
</RadialBarChart>
96-
</ResponsiveContainer>
97-
106+
{renderSVG(12)}
98107
{/* Centered Percentage for compact mode */}
99108
<div className="absolute inset-0 flex items-center justify-center pointer-events-none">
100109
<span className="text-[11px] font-bold text-foreground">
@@ -110,33 +119,7 @@ export default function CircleChart({
110119
return (
111120
<div className="flex flex-col items-center justify-center p-2">
112121
<div className="h-[90px] w-[90px] relative">
113-
<ResponsiveContainer width="100%" height="100%">
114-
<RadialBarChart
115-
cx="50%"
116-
cy="50%"
117-
innerRadius="70%"
118-
outerRadius="95%"
119-
barSize={8}
120-
data={data}
121-
startAngle={90}
122-
endAngle={-270}
123-
>
124-
<PolarAngleAxis
125-
type="number"
126-
domain={[0, 100]}
127-
angleAxisId={0}
128-
tick={false}
129-
/>
130-
<RadialBar
131-
background={{ fill: 'rgba(128, 128, 128, 0.1)' }}
132-
dataKey="value"
133-
cornerRadius={10}
134-
animationDuration={animationDuration}
135-
animationEasing="ease-out"
136-
/>
137-
</RadialBarChart>
138-
</ResponsiveContainer>
139-
122+
{renderSVG(10)}
140123
{/* Centered Percentage */}
141124
<div className="absolute inset-0 flex items-center justify-center pointer-events-none">
142125
<span className="text-base font-bold text-foreground drop-shadow-sm tracking-tight">

0 commit comments

Comments
 (0)