vue3中lottie-web封装组件和api的使用

前端程序媛Ying 2024-07-28 10:33:01 阅读 58

 

  使用ts的话定义类型components/Lottie/type.ts

<code>type Segment = [ number, number]

export interface LottieEvent {

play: () => void, // 播放动画

pause: () => void, // 暂停动画

stop: () => void, // 停止动画

setSpeed: (speed: number) => void, // 设置播放速度,1 表示1倍速度,0.5 表示 0.5倍速度

goToAndStop: (value: number, isFrame?: boolean) => void, // 跳到某一帧或某一秒停止,第二个参数 isFrame 为是否基于帧模式还是时间,默认为 false

goToAndPlay: (value: number, isFrame?: boolean) => void, // 跳到某一帧或某一秒开始,第二个参数 isFrame 为是否基于帧模式还是时间,默认为 false

setDirection: (direction: 1 | -1) => void, // 设置播放方向,1 表示正向播放,-1 表示反向播放

playSegments: (segments: Segment[], forceFlag?: boolean) => void, // 播放指定的片段,参数1为数组,两个元素为开始帧和结束帧;参数2为,是否立即播放片段,还是等之前的动画播放完成

destroy: () => void, // 销毁动画

getDuration: (isFrames: boolean) => void, // 获取动画时长,参数为是否基于帧模式,默认为 false. 如果为真,则返回以帧为单位的持续时间,如果为假,则以秒为单位。

[propname: string]: any

}

// Events

// onComplete - 播放完成时触发

// onLoopComplete - 循环播放完成时触发

// onEnterFrame - 每一帧播放时触发

// onSegmentStart - 播放指定片段开始时触发

封装组件 components/Lottie/index.vue 

<script setup>

import { ref, onMounted } from 'vue'

import lottie from 'lottie-web'

// 设置组件参数

const props = defineProps({

renderer: {

type: String,

default: 'svg',

},

// 循环播放

loop: {

type: Boolean,

default: true,

},

autoplay: {

type: Boolean,

default: true,

},

animationData: {

type: Object,

default: () => ({}),

},

name: {

type: String,

default: '',

}

})

// 创建 lottie 接收变量和获取dom

const animation = ref(null)

const dom = ref(null)

// 创建事件返回初始化lottie对象

const emits = defineEmits(['getAnimation', 'getDom'])

// 初始化渲染 lottie动画,并返回lottie对象

onMounted(() => {

animation.value = lottie.loadAnimation({

container: dom.value, // 用于渲染的容器

// 渲染方式 svg、canvas、html

renderer: props.renderer,

// 是否循环

loop: props.loop,

autoplay: props.autoplay, // 自动播放

// UED 提供的 动画的 json 文件

animationData: props.animationData,

name: props.name,

});

emits('getAnimation', animation.value)

})

</script>

<template>

<!-- 渲染 lottie 动画 -->

<div id="lottieId" ref="dom"></div>code>

</template>

<style scoped>

#lottieId {

width: 100%;

height: 100%;

}

</style>

引用组件,例如HelloWord.vue

<script setup>

import { ref, onMounted, watch } from 'vue'

import Lottie from './Lottie/index.vue'

import Animation from '../assets/Animation - 1712559820721.json'

import Animation1 from '../assets/Animation-1.json'

const a1 = ref(null)

const count = ref(0)

const likeFlag = ref(false)

const getAnimation = (animation) => {

a1.value = animation

if (a1.value) {

a1.value.addEventListener('enterFrame', () => {

// console.log(a1.value, '--a1.value--');

if (a1.value.currentFrame >= 63) { // 当前帧

a1.value.goToAndPlay(0, true) // 跳转到指定帧开始

}

})

a1.value.addEventListener('complete', () => {

console.log('播放完毕');

})

}

}

const play = () => {

if (likeFlag.value) {

a1.value.playSegments([31, 64], true) // 播放指定的片段,([开始帧,结束帧], 是否立即播放)

} else {

a1.value.playSegments([0, 30], true)

}

likeFlag.value = !likeFlag.value

count.value++

}

// const likeClick = () => {

// console.log('likeClick');

// a1.value.setSpeed(2) // 设置播放速度

// // a1.value.setDirection(-1) // 设置播放速度,不知道什么原因这里没有生效

// a1.value.stop()

// setTimeout(() => {

// // a1.value.goToAndStop(31, true) // 跳到指定帧结束,第二个参数 isFrame 为是否基于帧模式还是时间,默认为 false

// // a1.value.goToAndPlay(21, true) // 跳转到指定帧开始

// a1.value.play();

// }, 100); // 延迟100毫秒播放

// const duration = a1.value.getDuration(true) // true 为帧, false 为秒

// console.log(duration, '--duration--'); // 64帧 2.56秒

// }

// 监听鼠标滚动事件

let frame = 0

const maxFrame = 60; // 假设最大值为100

window.addEventListener('wheel', (event) => {

console.log(event, '--event--');

if (event.wheelDelta < 0) {

frame += 10

count.value++

} else if (event.wheelDelta >= 149) {

frame -= 10

count.value--

}

if (frame >= maxFrame) {

frame = 0; // 重置为0

} else if (frame < 0) {

frame = maxFrame; // 重置为最大值

}

a1.value.goToAndStop(frame, true)

console.log(frame, '--frame--');

})

onMounted(() => {

})

</script>

<template>

<div class="card">code>

<div>

<Lottie :animation-data="Animation" />code>

</div>

<div class="card-body">code>

<Lottie class="a1" :animation-data="Animation1" :loop="false" :autoplay="true" @get-animation="getAnimation"code>

@click="likeClick" />code>

<button @click="play">Play</button>code>

<div class="count">{ { count }}</div>code>

<div class="info">测试内容</div>code>

</div>

</div>

</template>

<style scoped>

.card {

display: flex;

align-items: center;

width: 700px;

/* margin: 0 auto; */

.card-body {

position: relative;

.info {

position: absolute;

left: 50%;

top: 20%;

transform: translate(-50%, -50%);

color: rgb(255, 255, 255);

}

}

}

</style>

 



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。