mifi / react-lottie-player

Fully declarative React Lottie player
MIT License
494 stars 52 forks source link

Is it possible to use dynamic animationData? #108

Closed modulareverything closed 9 months ago

modulareverything commented 9 months ago

I have a Lottie component that needs to play a different animation randomly, selected by a function. Unfortunately this doesn't seem to work, I guess it has something to do with it not being a json file but a string of json data instead. Is there any way I can achieve this without creating multiple instances of the same Lottie component?

import squareHoverOne from "public/lottie/1x1/HOVER_V1.json";
import squareHoverTwo from "public/lottie/1x1/HOVER_V2.json";
import squareHoverThree from "public/lottie/1x1/HOVER_V3.json";

function Animation() {
  function selectSquareHoverAnimation() {
    const animations = [squareHoverOne, squareHoverTwo, squareHoverThree];
    return animations[Math.floor(Math.random() * animations.length)];
  }

  return (
    <Lottie
      animationData={selectSquareHoverAnimation()}
      rendererSettings={{ preserveAspectRatio: "xMidYMid slice" }}
    />
  )
};

In reality my Lottie component is a bit more detailed, so you can see why I want to avoid creating multiple instances of it:

<Lottie
  ref={lottieRef}
  animationData={selectSquareHoverAnimation()}
  play={play}
  onEnterFrame={(e) => handleEnterFrame(e)}
  onLoopComplete={() => handleLoopComplete()}
  style={{ width: "100%", height: "100%" }}
  rendererSettings={{ preserveAspectRatio: "xMidYMid slice" }}
/>
modulareverything commented 9 months ago

Doing a bit more experimenting with this, it seems this works fine:

  function selectSquareHoverAnimation() {
    const animations = [squareHoverOne, squareHoverTwo, squareHoverThree];
    return animations[1];
  }

So I'm thinking there may be something wrong with my function.

modulareverything commented 9 months ago

Okay, turns out I didn't need to open this issue, I just had to improve my own code 😁

Hopefully this is at least useful to someone else. It was required to use the useMemo hook on this one to prevent the function from running multiple times when you hover, and therefore confusing the animationData. I'm not sure why that was happening, but useMemo did fix the problem.

Updated demo code:

import { useMemo } from "react";

import squareHoverOne from "public/lottie/1x1/HOVER_V1.json";
import squareHoverTwo from "public/lottie/1x1/HOVER_V2.json";
import squareHoverThree from "public/lottie/1x1/HOVER_V3.json";

function Animation() {
  const hoverAnimations = useMemo(() => {
    const animations = [squareHoverOne, squareHoverTwo, squareHoverThree];
    return animations[Math.floor(Math.random() * animations.length)];
  }, []);

  return (
    <Lottie
      animationData={selectSquareHoverAnimation} // note this is no longer a function, so () was removed
      rendererSettings={{ preserveAspectRatio: "xMidYMid slice" }}
    />
  )
};