前言
lottie 动画库适配小程序的版本,该库基于官方库进一步封装,用法和官方一致。
能找到这篇文章想必大家已经知道lottie动画是什么,以及有什么优点,这里就不多说了。
因官方库已经800年不维护更新了,UI给的较新版本的lottie json 动画文件使用该库已无法正常显示,故做了以下升级:
-
使用当前最新版本的 lottie 库,广泛支持更多版本的 lottie json 动画文件
- 截止到2025年3月,最新版本为2.12.2
-
精简项目,直接使用js文件,不再依赖lottie-web包,js文件从bodymovin libraries获取,想用哪个用哪个。
-
使用Rollup打包,支持 esm 和 cjs 两种模块化方式
-
内置Taro版本的组件,参考 examples/taro/LottieAnim
lottie 的相关介绍与动画生成方法等请参考官方说明
依赖小程序基础库版本 >= 2.8.0 的环境
选择库文件时,请选择 lottie_canvas.js 文件 或 lottie_canvas.min.js 文件,因为小程序使用canvas来绘制lottie动画
使用
可参考该代码片段:developers.weixin.qq.com/s/2TYvm9mJ7…。大致步骤如下:
- 通过 npm 安装:
npm install --save lottie-miniprogram-modern
2. 传入 canvas 对象用于适配
<canvas id="canvas" type="2d"></canvas>
import lottie from 'lottie-miniprogram-modern'
Page({
onReady() {
this.createSelectorQuery().select('#canvas').node(res => {
const canvas = res.node
lottie.setup(canvas)
}).exec()
}
})
3. 使用 lottie 接口
lottie.setup(canvas)
this.ani = lottie.loadAnimation({
...
})
this.ani.destroy() // 页面退出需销毁
在 Taro 中使用
/**
* @description lottie动画组件
*/
import Taro from '@tarojs/taro';
import { Canvas } from '@tarojs/components';
import { useImperativeHandle, forwardRef, useRef, useEffect } from 'react';
import lottie from 'lottie-miniprogram';
export interface WxLottieRef {
play: () => void;
pause: () => void;
stop: () => void;
destroy: () => void;
}
interface Props {
lottieId: string; // canvas id
width: number; // 宽度
height: number; // 高度
animationData?: any; // 动画数据本地json
path?: string; // 远程url
loop?: boolean; // 是否循环
autoplay?: boolean; // 是否自动播放
}
const LottieView = forwardRef<WxLottieRef, Props>((props, ref) => {
const {
lottieId = 'lottieCanvas',
animationData,
path,
width,
height,
loop = true,
autoplay = true,
} = props;
const lottieInstance = useRef<any>(null);
const canvasRef = useRef(null);
// 暴露组件方法
useImperativeHandle(ref, () => ({
play: () => lottieInstance.current?.play(),
pause: () => lottieInstance.current?.pause(),
stop: () => lottieInstance.current?.stop(),
destroy: () => {
lottieInstance.current?.destroy();
},
}));
const loadAnimation = () => {
if (!canvasRef.current) return;
const query = Taro.createSelectorQuery();
query.select(`#${lottieId}`)
.fields({ node: true, size: true })
.exec((res) => {
const canvas = res[0].node;
if (!canvas) {
console.error('Canvas element not found');
return;
}
const context = canvas.getContext('2d');
const dpr = Taro.getSystemInfoSync().pixelRatio;
canvas.width = width * dpr;
canvas.height = height * dpr;
context.scale(dpr, dpr);
lottie.setup(canvas);
// 如果已有动画实例,先销毁
if (lottieInstance.current) {
lottieInstance.current.destroy();
}
lottieInstance.current = lottie.loadAnimation({
renderer: 'canvas',
loop,
autoplay,
animationData,
path,
rendererSettings: {
context,
clearCanvas: true,
},
});
});
};
// 监听path和animationData变化
useEffect(() => {
if (path || animationData) {
loadAnimation();
}
}, [path, animationData]);
useEffect(() => () => {
// 组件卸载时清理动画实例
if (lottieInstance.current) {
lottieInstance.current.destroy();
}
}, []);
return (
<Canvas
id={lottieId}
type="2d"
ref={canvasRef}
style={{
width: Taro.pxTransform(width * 2),
height: Taro.pxTransform(height * 2),
}}
></Canvas>
);
});
export default LottieView;
// 引入组件
import LottieView from './LottieView';
// 使用组件
<LottieView lottieId="lottieCanvas" width={300} height={300} animationData={require('./animation.json')} />
接口
目前提供两个接口:
lottie.setup(canvas)
需要在任何 lottie 接口调用之前调用,传入 canvas 对象
lottie.loadAnimation(options)
与原来的 loadAnimation 有些不同,支持的参数有:
- loop
- autoplay
- animationData
- path (只支持网络地址)
- rendererSettings.context (必填)
说明
- 由于小程序本身不支持动态执行脚本,因此 lottie 的 expression 功能也是不支持的。
- 感兴趣的小伙伴可看看该项目实现,实际上就是使用lottie提供的web脚本,在小程序中做一系列补丁后,以让它可以在小程序环境下使用,项目地址 github.com/Pursue-LLL/…