mui / mui-x

MUI X: Build complex and data-rich applications using a growing list of advanced React components, like the Data Grid, Date and Time Pickers, Charts, and more!
https://mui.com/x/
4.55k stars 1.33k forks source link

[charts] Add animation to Gauge chart #15181

Open Annastrin opened 3 weeks ago

Annastrin commented 3 weeks ago

Summary

Can you please make the Gauge animated (like the Pie chart)?

Examples

No response

Motivation

No response

Search keywords: gauge animation

michelengelen commented 3 weeks ago

Thanks for opening this @Annastrin ... I am pretty sure this is on the teams radar already, but in case it isn't I'll add this to the board! 👍🏼

alexfauquette commented 2 weeks ago

That sounds nice, but il will come with somewhat a performance impact, because the <path /> will need to be recomputed each time.

The other option is to use a cursor, and apply some CSS transition/animation to it

romgrk commented 2 weeks ago

If you do the animation outside of React there shouldn't really be much of a perf cost to it (assuming you use this lightweight animate function):

diff --git a/packages/x-charts/src/Gauge/GaugeValueArc.tsx b/packages/x-charts/src/Gauge/GaugeValueArc.tsx
index b05975a86..29b723b65 100644
--- a/packages/x-charts/src/Gauge/GaugeValueArc.tsx
+++ b/packages/x-charts/src/Gauge/GaugeValueArc.tsx
@@ -32,8 +32,29 @@ export function GaugeValueArc(props: React.ComponentProps<'path'>) {
   const valueAngle =
     startAngle + ((value - valueMin) / (valueMax - valueMin)) * (endAngle - startAngle);

+  const ref = React.useRef(null)
+  React.useEffect(() => {
+    if (!shouldAnimate) { return undefined }
+
+    return animate({
+      from: startAngle,
+      to: valueAngle,
+      onChange: (angle: any) => {
+        ref.current.setAttribute('d',
+          d3Arc().cornerRadius(cornerRadius)({
+            startAngle,
+            endAngle: angle,
+            innerRadius,
+            outerRadius,
+          })
+        )
+      }
+    }).cancel
+  })
+
   return (
     <StyledPath
+      ref={ref}
       transform={`translate(${cx}, ${cy})`}
       d={
         d3Arc().cornerRadius(cornerRadius)({