chenqingspring / vue-lottie

Render After Effects animations on Vue based on Bodymovin
MIT License
1.31k stars 281 forks source link

How to handle multiple animations on the same page #49

Open AdamBD opened 4 years ago

AdamBD commented 4 years ago

I am creating multiple lottie elements on the same page, but because the 'last' one added to the dom becomes the last this.anim only the last animation is working. What is the way to handle multiple animations on the same page correctly?

 handleAnimation: function (anim) {
        this.anim = anim;
      },
cweachock commented 4 years ago

hey there, we were having this issue as well trying to get two instances from an exported JSON file to play the same animation with 2 different paths one for desktop and one for mobile. Is there a way to have 2 lottie wrappers on the same page to handle multiple animations?

mdicampli commented 4 years ago

Hi everyone, i think i found a workaround to solve this issue (in my case works properly). Here's my solution:

First i imported json data:

import * as downloadAnimationData from './assets/download.json'; 
import * as bookAnimationData from './assets/book.json';

then i created an object in data() like this:

animationsOptions: {
                    download: {
                        animationData: downloadAnimationData.default
                        // optionally you can add other option parameters here like: 
                        // autoplay: false
                    }, 
                    book: {
                        animationData: bookAnimationData.default
                    }
                },

In lottie wrapper element i changed :option property attribute to match my object schema:

<lottie :options="animationsOptions.book" :height="28" :width="28" v-on:animCreated="handleAnimation"/>

then i added an additional parameter tho the handleAnimation callback (and preserved $event passed object that carries animation data from lottie's animCreated) specifying the "type" of the animation:

<lottie :options="animationsOptions.book" :height="28" :width="28" v-on:animCreated="handleAnimation($event, 'book')"/>

so i changed my methods according to populate main data()'s anim object and select right anim in play() and stop() methods calls:

methods: {
            handleAnimation: function (anim, type) {
                this.anim[type] = anim;
            },
            play: function (type) {
                this.anim[type].play();
            },
            stop: function (type) {
                this.anim[type].stop();
            },
        }

Example of usage with autoplay: false and hover action

<a href="#" @mouseover="play('book')" @mouseleave="stop('book')"> <lottie :options="animationsOptions.book" :height="28" :width="28" v-on:animCreated="handleAnimation($event, 'book')"/> <span>Read more</span></a>

Hope that this can help someone :)

Hruskasvestka commented 3 years ago

Hey there! I found kinda same solution as @mdicampli but with different :options. I will try to describe step by step down below.

  1. Import vue-lottie and JSON data :

    import Lottie from 'vue-lottie';
    import * as downloadAnimationData from '../assets/icons-lottie/download.json';
    import * as coinAnimationData from '../assets/icons-lottie/coin.json';
    import * as arrowAnimationData from '../assets/icons-lottie/arrow.json';
  2. Create an object:

    export default { 
    components: {
    Lottie
    },
    data() {
    return {
      defaultOptions: {
        download: {
          animationData: downloadAnimationData.default
        },
        coin: {
          animationData: coinAnimationData.default
        },
        arrow: {
          animationData: arrowAnimationData.default
        }
      },
      animationSpeed: 1
    };
    },
    };
  3. And that relevant changes are coming in DOM:

    <lottie
    :options="defaultOptions.download" // main issue
    :height="45"
    :width="45"
    style="margin: 0 20px 0 -10px;" // you can add your own style here
    />
    <lottie
    :options="defaultOptions.coin" // main issue
    :height="45"
    :width="45"
    style="margin: 0 20px 0 -10px;"  // you can add your own style here
    />

    Instead of using animationsOptions.download in :option use defaultOptions.download.

yogsky commented 3 years ago

Can anybody please confirm they are able to run 5 or more animations in the same page without page turning unresponsive ? I tried to run 7 instances of with autoplay off, and boom my app crashes 🙁

Hruskasvestka commented 3 years ago

Can anybody please confirm they are able to run 5 or more animations in the same page without page turning unresponsive ? I tried to run 7 instances of with autoplay off, and boom my app crashes 🙁

Yes, it's possible to implement many animations in the same page.

sddsaw commented 2 years ago

有demo吗

vedmant commented 2 years ago

I used simpler solution:

LottieWrapper.vue

<template>
  <client-only>
    <Lottie v-bind="$attrs" :key="name" v-on="$listeners" />
  </client-only>
</template>

<script>
export default {
  components: {
    Lottie: process.client ? require('vue-lottie').default : null,
  },

  props: {
    name: { type: String, required: true },
  },
}
</script>

It needs unique name for each animation.

sddsaw commented 2 years ago

vue-lottie 将动画转换为json的插件是嘛,我用过这个插件

------------------ 原始邮件 ------------------ 发件人: "chenqingspring/vue-lottie" @.>; 发送时间: 2021年12月23日(星期四) 中午12:51 @.>; @.**@.>; 主题: Re: [chenqingspring/vue-lottie] How to handle multiple animations on the same page (#49)

I used simpler solution:

LottieWrapper.vue <template> <client-only> <Lottie v-bind="$attrs" :key="name" v-on="$listeners" /> </client-only> </template> <script> export default { components: { Lottie: process.client ? require('vue-lottie').default : null, }, props: { name: { type: String, required: true }, }, } </script>
It needs unique name for each animation.

— Reply to this email directly, view it on GitHub, or unsubscribe. Triage notifications on the go with GitHub Mobile for iOS or Android. You are receiving this because you commented.Message ID: @.***>