kevinsqi / react-circular-progressbar

A circular progressbar component, built with SVG and extensively customizable
http://www.kevinqi.com/react-circular-progressbar
MIT License
1.09k stars 132 forks source link

AnimatedProgressProvider is outdated #239

Open hoixw opened 4 months ago

hoixw commented 4 months ago

The package react-move, used in the docs, is quite outdated. It doesn't support react v18, which is required by next.js 13 and frameworks. You can easily rewrite it in framer-motion.

Example animatedProgressProvider:

import React, { useEffect, useState } from "react";
import { motion, useAnimation } from "framer-motion";

const AnimatedProgressProvider = ({
  valueStart = 0,
  valueEnd,
  duration,
  easingFunction,
  children,
  repeat = false
}) => {
  const controls = useAnimation();
  const [value, setValue] = useState(valueStart);

  useEffect(() => {
    const animate = async () => {
      await controls.start({
        value: valueEnd,
        transition: { duration, ease: easingFunction }
      });

      if (repeat) {
        await controls.start({
          value: valueStart,
          transition: { duration: 0 }
        });
      }
    };

    animate();

    if (repeat) {
      const interval = setInterval(animate, duration * 1000);
      return () => clearInterval(interval);
    }
  }, [controls, valueEnd, valueStart, duration, easingFunction, repeat]);

  return (
    <motion.div
      initial={{ value: valueStart }}
      animate={controls}
      onUpdate={latest => setValue(latest.value)}
    >
      {children(value)}
    </motion.div>
  );
};

export default AnimatedProgressProvider;

Example app.jsx:

import React from "react";
import { CircularProgressbar, buildStyles } from "react-circular-progressbar";
import "react-circular-progressbar/dist/styles.css";
import { easeQuadInOut } from "d3-ease";
import AnimatedProgressProvider from "./AnimatedProgressProvider";

const App = () => (
  <div style={{ width: 200 }}>
    <AnimatedProgressProvider
      valueStart={0}
      valueEnd={66}
      duration={1.4}
      easingFunction={easeQuadInOut}
    >
      {(value) => {
        const roundedValue = Math.round(value);
        return (
          <CircularProgressbar
            value={value}
            text={`${roundedValue}%`}
            styles={buildStyles({ pathTransition: "none" })}
          />
        );
      }}
    </AnimatedProgressProvider>
  </div>
);

export default App;