LottieFiles / lottie-interactivity

A small javascript library to enable interactivity with Lottie animations
https://lottiefiles.com/interactivity
MIT License
430 stars 55 forks source link

Can't seem to get lottie player with interactivity working in vue component #75

Closed toddpadwick closed 2 years ago

toddpadwick commented 2 years ago

Overview

I am trying to use lottie player with interactivity in a vue component. As Im using Nuxt, I have lottieplayer imported via nuxt plugins on clientside, and that works fine alone. The player can run the animation as normal, but what I can't figure out is how to get the interactivity to work. I have followed the example in the docs and set it up as below. But the load event doesn't fire. Does anyone know how I get this to work?

<template>
      <div class="shift-animation" ref="container">
          <lottie-player ref="lottie" id="shiftAnimation" mode="normal":src="combinedAnimationSrc"/>
      </div>
</template>

<script>

  import combinedAnimation from '~/assets/lottie/shift-combined.json';
  import { create } from '@lottiefiles/lottie-interactivity';

  export default {
    data() {
      return {
        combinedAnimationSrc:JSON.stringify(combinedAnimation)
      }
    },
    mounted() {
        // 2. listen for player load. See lottie player repo for other events
        if (process.client) {
            const lottie = this.$refs.lottie;
            if (lottie) {
                console.log('lottie exists');
                this.$refs.lottie.addEventListener('load', function() {
                  // 3. configure the interactivity library
                  console.log('loaded');
                  create({
                    mode: 'scroll',
                    player: '#shiftAnimation',
                    actions: [
                      {
                        visibility: [0, 1],
                        type: 'seek',
                        frames: [0, 100],
                      },
                    ],
                  });
                })
            }
        }
    },

...

samuelOsborne commented 2 years ago

hey @toddpadwick, could you try replacing the 'load' event with 'ready' ?

toddpadwick commented 2 years ago

Thanks @samuelOsborne that seems to have solved the loaded issue. but I am now getting a new issue:

Screenshot 2022-04-12 at 17 32 37

FYI, what I am trying to achieve is the following:

I am essentially re-creating the animation on this site, but using lottie (its currently a series of gifs which is very clunky).

samuelOsborne commented 2 years ago

@toddpadwick Im having trouble recreating this error, are you using the latest version of Lottie-Interactivity?

For your second point, the library doesn't support playing segments for X amount of seconds, only when they're finished or for a certain amount of frames. However I just added the nextInteraction() and jumpTo(index) methods which give you full control over which actions you want to use when using the chain mode of Lottie-Interactivity: https://lottiefiles.com/interactivity#LI-chaining

This event fires when a transition happens:

The 'transition' event is fired from the lottie-player element every time a transition occurs. The event contains the following details:
oldIndex
newIndex
toddpadwick commented 2 years ago

Okay, so I've updated it to try a chain event and updated to latest player and lottie interactivity. now using this code:

<template>
      <div class="shift-animation" ref="container">
          <lottie-player ref="lottie" id="shiftAnimation" mode="normal" :src="combinedAnimationSrc"/>
      </div>
</template>

<script>

  import combinedAnimation from '~/assets/lottie/shift-combined.json';
  import { create } from '@lottiefiles/lottie-interactivity';

  export default {
    data() {
      return {
        combinedAnimationSrc:JSON.stringify(combinedAnimation)
      }
    },
    mounted() {
        if (process.client) {
            const lottie = this.$refs.lottie;
            if (lottie) {
                console.log('lottie exists');
                lottie.addEventListener('ready', () => {
                  // 3. configure the interactivity library
                  console.log('loaded');
                  create({
                    mode: 'chain',
                    player: '#shiftAnimation',
                    actions: [
                        {
                            state: 'loop',
                            transition: 'click',
                            frames: [0,4]
                        },
                        {
                            state: 'autoplay',
                            transition: 'onComplete',
                            frames: [4,8]
                        },
                        {
                            state: 'autoplay',
                            transition: 'onComplete',
                            frames: [8,12],
                            reset: true
                        }
                    ]
                  });
                })
            }
        }
    },

But I am getting this error: Screenshot 2022-04-12 at 18 49 55

I don't know where it's got 'undefined.json' from. If I remove the on load function, the json loads fine but obviously just doesn't play.

Sorry if I'm being thick!

samuelOsborne commented 2 years ago

@toddpadwick your whole process.client code needs to be in the mounted() hook, hopefully that should resolve the issue. Someone else had this on the lottie-player repo

toddpadwick commented 2 years ago

Oops sorry, it is, I just copied and pasted it wrong. I've just updated the code snippet above.

samuelOsborne commented 2 years ago

@toddpadwick Solved it on my end by wrapping the lottie-player with

<client-only>
 <lottie-player>
</client-only>

Let me know if it works on your end

samuelOsborne commented 2 years ago

Ah, this removes the error but then we don't have the ref on the mounted hook..

Is using a URL not possible for the source of the animation?

I was trying to see if using the static folder worked otherwise but haven't gotten a result yet

toddpadwick commented 2 years ago

ah yes I was just commenting the same issue :( Url didn't seem to work as for some reason it needed to re-parsed as JSON and then applied as a variable.

samuelOsborne commented 2 years ago

Using like this doesn't work?

<lottie-player ref="lottie" id="shiftAnimation" autoplay src="https://assets8.lottiefiles.com/private_files/lf30_tnblylie.json"></lottie-player>
toddpadwick commented 2 years ago

Awesome, Its working!! Thank you! Turns out loading the required lottie file from assets wasn't playing ball with . So I've instead moved the lottie file to the static folder and loading it the classic way.

I've also got the chaining to trigger the text change event :) https://stage.thewriter.co.uk/

Thanks for your help.

FYI, for anyone else who needs help - here is my code:

<template>
      <div class="shift-animation" ref="container">

          <lottie-player ref="lottie" id="shiftAnimation" mode="normal" src="/lottie/shift-combined.json"/>

      </div>
</template>

<script>

  import combinedAnimation from '~/assets/lottie/shift-combined.json';
  import { create } from '@lottiefiles/lottie-interactivity';

  export default {
    data() {
      return {
        combinedAnimationSrc:JSON.stringify(combinedAnimation)
      }
    },
    mounted() {
        if (process.client) {
            const lottie = this.$refs.lottie;
                lottie.addEventListener('ready', () => {
                  create({
                    mode: 'chain',
                    player: '#shiftAnimation',
                    actions: [
                        {
                            state: 'loop',
                            transition: 'repeat',
                            repeat:4,
                            frames: [0,9]
                        },
                        {
                            state: 'loop',
                            transition: 'repeat',
                            repeat:4,
                            frames: [10,18]
                        },
                        {
                            state: 'loop',
                            transition: 'repeat',
                            repeat:4,
                            frames: [19,27]
                        },
                        {
                            state: 'loop',
                            transition: 'repeat',
                            repeat:4,
                            frames: [28,36]
                        },
                        {
                            state: 'loop',
                            transition: 'repeat',
                            repeat:4,
                            frames: [37,45]
                        },
                        {
                            state: 'loop',
                            transition: 'repeat',
                            repeat:12,
                            frames: [47,54],
                            reset: true
                        }
                    ]
                  });
                })
                lottie.addEventListener('transition', (e) => {
                    if (e && e.detail) {
                        this.$emit('new-segment',e.detail.newIndex); // emit segment change to parent Vue component
                    }
                })

        }
    }
  }

</script>
samuelOsborne commented 2 years ago

Ah it had to be put as the src attribute! Nice one, the site looks great too!

Closing this now, cheers!

toddpadwick commented 2 years ago

Hi @samuelOsborne The animation is working for the most part, however, it sometimes doesn't trigger the animation to start on a fresh page load. I am guessing the 'ready' event is not being triggered when everything is properly loaded and ready to be initiated. I haven't changed anything since the above code was implemented. Any ideas what else I can try? I know we tried 'load' before and that caused other problems as you know. Heres the staging site https://stage.thewriter.co.uk/

toddpadwick commented 2 years ago

Hi @samuelOsborne still having issues with this. Often, the animation doesn't initially play on hard refresh or load, even though it is listening for the ready event. https://www.thewriter.com/