Code Monkey home page Code Monkey logo

react-lottie-player's Introduction

Fully declarative React Lottie player

Inspired by several existing packages wrapping lottie-web for React, I created this package because I wanted something that just works and is easy to use. None of the alternatives properly handle changes of props like playing/pausing/segments. This lead to lots of hacks to get the animations to play correctly.

react-lottie-player is a complete rewrite using hooks ๐ŸŽฃ for more readable code, easy to use, seamless and fully declarative control of the lottie player.

Tests NPM JavaScript Style Guide

Features

Install

npm install --save react-lottie-player

Usage

import React from 'react'

import Lottie from 'react-lottie-player'
// Alternatively:
// import Lottie from 'react-lottie-player/dist/LottiePlayerLight'

import lottieJson from './my-lottie.json'

export default function Example() {
  return (
    <Lottie
      loop
      animationData={lottieJson}
      play
      style={{ width: 150, height: 150 }}
    />
  )
}

Example

Screenshot

๐ŸŽ› Live demo

๐Ÿ‘ฉ๐Ÿฟโ€๐Ÿ’ป Example code

Lazy loading

Option 1: React code splitting (React.lazy)

Extract your Lottie animation into a separate component, then lazy load it:

// MyLottieAnimation.jsx

import Lottie from 'react-lottie-player';
import animation from './animation.json';

export default function MyLottieAnimation(props) {
  return <Lottie animationData={animation} {...props} />;
}

// MyComponent.jsx

import React from 'react';
const MyLottieAnimation = React.lazy(() => import('./MyLottieAnimation'));

export default function MyComponent() {
  return <MyLottieAnimation play />;
}

Option 2: dynamic import with state

const Example = () => {
  const [animationData, setAnimationData] = useState<object>();

  useEffect(() => {
    import('./animation.json').then(setAnimationData);
  }, []);

  if (!animationData) return <div>Loading...</div>;
  return <Lottie animationData={animationData} />;
}

Option 3: path URL

const Example = () => <Lottie path="https://example.com/lottie.json" />;

Imperative API (ref)

const lottieRef = useRef();

useEffect(() => {
  console.log(lottieRef.current.currentFrame);
}, [])

return <Lottie ref={lottieRef} />;

See also #11

LottiePlayerLight

The default lottie player uses eval. If you don't want eval to be used in your code base, you can instead import react-lottie-player/dist/LottiePlayerLight. For more discussion see #39.

Lottie animation track scrolling div

See example/App.jsx (ScrollTest) in live example.

Resize mode: cover

If you want the animation to fill the whole container, you can pass this prop. See also #55:

<Lottie rendererSettings={{ preserveAspectRatio: 'xMidYMid slice' }} />

API

See type definitions and lottie-web.

Releasing

  • Commit & wait for CI tests
  • np

Credits

License

MIT ยฉ mifi


Made with โค๏ธ in ๐Ÿ‡ณ๐Ÿ‡ด

More apps by mifi.no

Follow me on GitHub, YouTube, IG, Twitter for more awesome content!

react-lottie-player's People

Contributors

davidlpc1 avatar dependabot[bot] avatar hood avatar jpwallace22 avatar kb-ig avatar kcirtaptrick avatar kdederichs avatar lachieh avatar mifi avatar mpeyper avatar rodbs avatar simonpkerr avatar slevisp avatar thomasmarren avatar vgpena avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-lottie-player's Issues

Animation blinking when animationData changes

I have a text input. Whatever I type in this input I update the JSON. So whenever I update the JSON the animation is blinking. Is there anyway it will not blink on every typing. Animation will remain as it is only the change I want will effect on the animation?

goTo flashing first frame by default when other frames are specified

@mifi
I have a lottie.json which have below markers

"markers": [
    { "tm": 0, "cm": "{\r\"name\":\"remove_background\"\r}", "dr": 25 },
    { "tm": 25, "cm": "{\r\"name\":\"removing_background\"\r}", "dr": 25 },
    { "tm": 50, "cm": "{\r\"name\":\"restore_background\"\r}", "dr": 25 },
    { "tm": 75, "cm": "{\r\"name\":\"loop_preloader_gradient\"\r}", "dr": 50 },
    { "tm": 125, "cm": "{\r\"name\":\"loop_preloader_bright\"\r}", "dr": 50 }
  ]

And I am trying to load the "loop_preloader_gradient " marker like named markers.

import Lottie from 'react-lottie-player';

function LoopyPreloader({ animationData, goTo }) {
  return (
    <Lottie
      loop={true}
      play={true}
      animationData={animationData}
      goTo={goTo} // loop_preloader_gradient
      style={{ width: 68, height: 68 }}
    />
  );
}

This causes a 2 seconds blink of "remove_background" animation and then renders "loop_preloader_gradient"

How to set rendererSetting?

In react-lottie we could set it this way
const defaultOptions = { loop: true, autoplay: true, animationData: lottieChar, rendererSettings: { preserveAspectRatio: "xMidYMid meet", }, };
but I don't know how to set it in your lib. I'm a newbie so could be nice if you could provide some example:) .

Export LottieProps

How would you feel about exporting the LottieProps type?

I think it would be handy in scenarios where we may want to offload some logic that determine what props to pass in to the player so that it's outside of the main component that renders the player. As an over-simplified example:

const getLottieProps = (componentProps: MyProps): LottieProps => {
  // Some logic that determines the props
  const play = true;
  const goTo = 123;
  return { play, goTo };
}

const MyComponent = (props: MyProps) => {
  return (
    <div className='my-animation'>
      <AnimationHeader/>
        <Lottie {...getLottieProps(props)}/>
      <AnimationFooter/>
    </div>
    );
}

Play on hover

I can't find a prop to play my animation on hover.

react-lottie-player fails on complex text rendering

I am working on a multi-language project with react-lottie-player. There are languages such as Thai, Burmese and Khmer that aren't using latin character like English, but abugidas where consonants are merged together with vowels to form one new character, for example: แ€† + แ€ป => แ€†แ€ป. However, to my observation, react-lottie-player splits all characters and renders them separately. Therefore "แ€†แ€ป" would be rendered as แ€† แ€ป. Is there a solution to this problem? Many thanks.

e.g. Burmese rendering:
lottie_breaks_down

How do I make elements responsive?

I'd like to use my json as a background element with object-fit:cover. I'm a little stuck. Currently running tailwind, nextjs, and react(duh)

`ref` Type incorrect

Currently the type of the ref prop on the Player component is inherited from the HTMLDivElement, but in the source the Lottie instance is passed to the forwarded ref.

Type inheriting here:

export type LottieProps = React.DetailedHTMLProps<
React.HTMLAttributes<HTMLDivElement>,
HTMLDivElement
> &
Partial<Pick<AnimationConfig<RendererType>, 'loop' | 'renderer' | 'rendererSettings' | 'audioFactory'>> & {
play?: boolean
goTo?: number
speed?: number
direction?: AnimationDirection
segments?: AnimationSegment | AnimationSegment[]
useSubframes?: boolean
onComplete?: AnimationEventCallback
onLoopComplete?: AnimationEventCallback
onEnterFrame?: AnimationEventCallback
onSegmentStart?: AnimationEventCallback
} & ({ path?: string } | { animationData?: object })

Lottie ref assigned here:

const setLottieRefs = useCallback((newRef) => {
animRef.current = newRef;
// eslint-disable-next-line no-param-reassign
if (forwardedRef) forwardedRef.current = newRef;
}, []); // eslint-disable-line react-hooks/exhaustive-deps

I am happy to assist with correcting this by exposing the animElementRef prop and correcting the types for both if a PR would be accepted.

Lazy loading animation data would be very handy

This might be far beyond the scope of this library - but being able to load animation data when it enters the viewport would be great.

Including animation data via import is good, but if you've got quite a few complex animations on a page, this can increase your bundle size real fast. Particularly if inline bitmaps are part of an animation. I'm working on a project where our average lottie json is ~1mb, and we've got like 6 per page. That's a chunky bundle! A chunky bundle that's getting in the way of my performance scores!

A lazyload feature, built into a library like this could be hella handy. Something like

<Lottie
    loop
    play
    animationData={'./some/static/path.json'}
    lazyLoad
    placeholder={placeholder.svg}
/>

The Interaction Observer API would be perfect to check if the lottie is in viewport - then if it is, fetch the json and fire up the animation.

Would be very nice.

No way to play back smoothly after using segments

When I go from segment 15 to 94 for example onClick it stops there and this is fine, but how to go from that position again back and play it smoothly back?

I tried

  • reverse segment 94 to 15
  • reverse segment with direction 94 to 15 with -1 direction
  • only direction -1 with play

and none of them work properly.

If there is no way currently to do this we really need a function playTo where it play to a segment no matter if forward or backward, but if there is any way please help me out on this one.

Thanks

Stop at last frame after completing animation

@mifi
I want animation to stop at the last frame once animation completes, I am try this

last_frame = PlayerRef.current.state.instance.totalFrames
PlayerRef.current.goTo(last_frame)

Doesn't seem to work, is there any alternative to this.

Lazy loading example throws typescript error

Small thing, but typescript will throw an error on the following line:

const [animationData, setAnimationData] = useState();

simple solution is to add a null to the initial useState:

const [animationData, setAnimationData] = useState(null);

Play on click

Hi! Is there a way to make it so the animation plays all the way through (once) when clicked on? (as well as on in initial load)

Include types in package

Really like the package, would be great to include the types for TypeScript support. If I find the time I will try and raise a PR to do this.

Unable to play backwards with Next.js

Thanks for a great package. Have been using it a few months and it's been working great. https://lightmillmedia.com. The menu icon on the site is a Lottie animation. Plays forwards onClick and reversed on the second click. The live site is on an older version of the package.

Initially I used CRA to bootstrap the project and all is working fine. Now I'm migrating to Next.js and while my animations work I can no longer play them backwards onClick, they just jump to frame zero. I can only get them to play backwards if loop is enabled but this also leads to the animation jumping about.

Is there a reason this would be the case when using Next. I have updated to the most recent version but the issue persists. Any help would be appreciated , thanks!

export LottieProps

Hi, Thank you for the great component!

I have a question,
Is there any way I can import LottieProps type to my project?

Not rendering in Gatsby

Howdy ๐Ÿ‘‹

To start off with, my issue is (from the looks of it?) pretty similar to #10.

I generated this lottie animation with After Effects + Lottiefiles. The animation is just images[1], rigged with Duik, baked with EasyBake, and then rendered.

It plays fine on lottiefiles.com, in the After Effects preview pane, and even on my phone.

Therefore, I saved the animation (clown-dance.json) to disk and tried to plug it into a component:

import * as React from 'react'
import Lottie from 'react-lottie-player'
import * as animationData from '../../anim/clown-dance.json'

const DisplayAnimation = () => {
  return (
    <>
      <h1>DisplayAnimation.tsx</h1>
      <Lottie
        loop
        animationData={animationData}
        play
        style={{ width: 300, height: 300 }}
        renderer='canvas'
      />
    </>
  )
}

export default DisplayAnimation

but no dice:
image

The console has nothing to say, except a warning from React Hot Loader (probably gatsby's fault?).

Additionally,

When I set the renderer prop to svg, I get these errors:
image

Any ideas?

[1] Which I suspect is the issue

Warning: ForwardRef: Support for defaultProps will be removed from memo components in a future major release. Use JavaScript default parameters instead.

I get this console.error message in my component that wraps react-lottie-player:

Warning: ForwardRef: Support for defaultProps will be removed from memo components in a future major release. Use JavaScript default parameters instead.

version 1.5.4

edit: should mention, everything works fine and it's still useful! just looking to get rid of the error message

Is it possible to use dynamic animationData?

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" }}
/>

react-lottie-player is not working in production mode but it is working fine in localhost

I'm working in next js and I user react-lottie-player. it is working fine in local host but is not working in production mode.. please
help me..
here is production link

import React, { useEffect } from "react";
import Lottie from "react-lottie-player";
import LottieImage1 from "../../public/static/1.json";
import LottieImage2 from "../../public/static/2.json";
import LottieImage3 from "../../public/static/3.json";

function AnimationFile({ file }) {
 const [windowScreen, setWindowScreen] = React.useState(0);
 const [responsive, setResponsive] = React.useState(0):
 const [defaultOptions, setDefaultOptions] = React.useState({
   loop: true,
   autoplay: true,
   animationData: LottieImage1,
   rendererSettings: {
     preserveAspectRatio: "xMidYMid slice",
   },
 });

 useEffect(() => {
   setWindowScreen(window.innerWidth);
   setResponsive(window.innerWidth - 50);
 }, []);

 useEffect(() => {
   if (file === "1") {
     setDefaultOptions((prev) => ({
       ...prev,
       animationData: LottieImage1,
     }));
   } else if (file === "2") {
     setDefaultOptions((prev) => ({
       ...prev,
       animationData: LottieImage2,
     }));
   } else if (file === "3") {
     setDefaultOptions((prev) => ({
       ...prev,
       animationData: LottieImage3,
     }));
   }
 }, [file]);

 return (

   <Lottie
     loop
     animationData={defaultOptions.animationData}
     play
     style={{
       width: windowScreen < 500 ? responsive - 50 : 600,
       height: windowScreen < 500 ? responsive - 50 : 600,
     }}
   />
 );
}

export default  #AnimationFile;

Typescript support

Just tried to add @types/react-lottie-player and it looks like the package doesn't exist. Would be nice to have some type declarations to have full TS support. Is there any plan to add this in the future?

Play backwards not working without loop

Hi,

First of all thanks for creating this package. Much less buggy than the original! I have come across an issue however-

Play in reverse with the direction=-1 and loop=false does not work. Playing in reverse only seems to work if loop=true. I've taken a look at the live example usage and the same issue happens. I would really like to implement a backwards play without having to do some loop=true/false trickery

Thanks

Type 'number[][]' is not assignable to type 'AnimationSegment | AnimationSegment[]'.

I'm using react, nextjs, and typescript. My lottie component plays the first 23 frames once, followed by the rest of the frames on a loop. I send an array to the prop 'segments'. Everything renders totally fine, but linting returns this error:

Type 'number[][]' is not assignable to type 'AnimationSegment | AnimationSegment[]'.
  Type 'number[][]' is not assignable to type 'AnimationSegment[]'.
    Type 'number[]' is not assignable to type 'AnimationSegment'.
      Target requires 2 element(s) but source may have fewer.ts(2322)
index.d.ts(18, 7): The expected type comes from property 'segments' which is declared here on type 'IntrinsicAttributes & PropsWithChildren<LottieProps>'

Here's my code:

import React from 'react'
import Lottie from 'react-lottie-player'
import VarHPattern from '../../data/Patterns_Blue_Dark.json'

export default function Pattern() {
  const playFrames = [
    [0, 23],
    [24, 95],
  ]
  return (
    <Lottie
      animationData={VarHPattern}
      loop
      segments={playFrames}
      play
      rendererSettings={{ preserveAspectRatio: 'xMidYMid slice' }}
      style={{ height: '100%' }}
    />
  )
}

Like I said, it's not breaking anything. It is, however, driving me crazy when I go to lint everything prior to production. Any ideas?

React 18 support

From my knowledge there shouldn't be any changes in react 18 that impacts this library, would love to see support for it.

How to animate specific part

Hello,

I want to animate the specific part of the Logo, I have used the react-lottie-player package and put all the necessary props.

Here below, is the code that I have integrated. I want to animate only the last character of my logo.

<Lottie
     loop
     animationData={animationData.default}
     play
     segments={[0,80]}
     style={{ width: 150, height: 100 }}
   />

in animationData.default I have passed the JSON of the logo.

Can you please help me to get the expected output?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.