这是效果图
安装依赖
- lottie-web
cnpm -i -S lottie-web
代码片段
组件结构
tabbar页面
这里我使用的是vant的tabbar
<template>
<view>
<router-view />
<van-tabbar route v-model="active" @change="onChange">
<van-tabbar-item
replace
:to="item.pagePath"
:name="index"
v-for="(item, index) in tabbarList"
:key="index"
>
<template #icon="props">
<lottie
:active="props.active"
:size="28"
:src="props.active ? item.selectedIconPath : item.iconPath"
></lottie>
</template>
<text>{{ item.text }}</text>
</van-tabbar-item>
</van-tabbar>
</view>
</template>
<script setup lang="ts">
import lottie from './lottie';
const homeNotSelected = require('./assets/home-notselected.json');
const homeSelected = require('./assets/home-selected.json');
const lianluoNotSelected = require('./assets/lianluo-notselected.json');
const lianluoSelected = require('./assets/lianluo-selected.json');
const meNotSelected = require('./assets/me-notselected.json');
const meSelected = require('./assets/me-selected.json');
const active = ref(0);
interface tabbarItem {
pagePath: string;
text: string;
iconPath: JSON;
selectedIconPath: JSON;
}
const tabbarList: Array<tabbarItem> = [
{
pagePath: '/pages/home/index',
text: '首页',
iconPath: homeNotSelected,
selectedIconPath: homeSelected,
},
{
pagePath: '/pages/llz/index',
text: '联络站',
iconPath: lianluoNotSelected,
selectedIconPath: lianluoSelected,
},
{
pagePath: '/pages/me/index',
text: '我的',
iconPath: meNotSelected,
selectedIconPath: meSelected,
},
];
</script>
<style lang="scss"></style>
lottie页面
<template>
<view>
<view
:id="lottieBox"
:style="[{ width: size + 'px' }, { height: size + 'px' }]"
></view>
</view>
</template>
<script setup lang="ts">
import lottie from 'lottie-web';
import { AnimationItem } from 'lottie-web/build/player/lottie';
let { ctx } = getCurrentInstance();
let animation: AnimationItem = null;
const lottieBox = ref<string>(
((): string => {
// 生成一个随机的ID
let result = [];
for (let i = 0; i < 6; i++) {
let ranNum = Math.ceil(Math.random() * 25);
result.push(String.fromCharCode(65 + ranNum));
}
return result.join('');
})()
);
const props = withDefaults(
defineProps<{
src: object;
size: number;
active: boolean;
}>(),
{
size: 28,
active: true,
}
);
watch(
() => props.active,
(newVal: boolean, oldVal: boolean) => {
// 当前选中和上一个被选中的都播放动画
play();
}
);
onMounted(() => {
animation = lottie.loadAnimation({
container: document.getElementById(lottieBox.value),
renderer: 'svg',
loop: false,
autoplay: true,
animationData: props.src,
});
if (!props.active) {
stop();
}
animation.addEventListener('enterFrame', (event) => {
if (event.currentTime > event.totalTime - 2) {
// 当lottie播放到小于最后两帧的时候停留到最后第三帧,如果不这样做lottie播放完后会隐藏
stop();
}
});
});
const play = () => {
animation.goToAndPlay(0, true);
};
const stop = () => {
animation.goToAndStop(animation.getDuration(true) - 3, true);
};
</script>
<style lang="scss"></style>