DoneDeal0
DoneDeal0

Reputation: 6267

How to animate number with Framer Motion?

I'm migrating an app from react-spring to framer-motion. With Spring, I can animate a number with:

export default function MyNumber({ number }) {
  const spring: any = useSpring({ from: { number: 0 }, to: { number } });
  return (
    <animated.div>
      {spring.number.interpolate((c) => c.toFixed(1))}
    </animated.div>
  );
}

I don't see how to do it with Framer-Motion.

Upvotes: 5

Views: 4566

Answers (2)

jdnichollsc
jdnichollsc

Reputation: 1569

if you want to use a hook for better reusability, try this other approach:

import { useEffect, useState } from 'react';
import { animate } from 'framer-motion';

export const useAnimatedCounter = (
  maxValue: number,
  initialValue = 0,
  duration = 1,
) => {
  const [counter, setCounter] = useState<number>(initialValue);

  useEffect(() => {
    const controls = animate(initialValue, maxValue, {
      duration,
      onUpdate(value) {
        setCounter(value);
      }
    });
    return () => controls.stop();
  }, [initialValue, maxValue, duration]);

  return counter;
}

Upvotes: 0

DoneDeal0
DoneDeal0

Reputation: 6267

So I've found the answer:

import { animate } from "framer-motion";
import React, { useEffect, useRef } from "react";

function Counter({ from, to }) {
  const ref = useRef();

  useEffect(() => {
    const controls = animate(from, to, {
      duration: 1,
      onUpdate(value) {
        ref.current.textContent = value.toFixed(1);
      }
    });
    return () => controls.stop();
  }, [from, to]);

  return <p ref={ref} />;
}

export default function App() {
  return <Counter from={0} to={65.4} />;
}

Upvotes: 2

Related Questions