官网:Lottie is a mobile library for Web, and iOS that parses Adobe After Effects animations exported as json with Bodymovin and renders them natively on mobile! Lottie Docs
作用:
Lottie是一个库,可以解析使用AE制作的动画(需要用bodymovin导出为json格式),支持web、ios、android和react native。在web侧,lottie-web库可以解析导出的动画json文件,并将其以svg或者canvas的方式将动画绘制到我们页面中。
优点:
Lottie方法方案是由设计师出动画,导出为json,给前端播放。所以,使用Lottie方案的好处在于:
- 动画由设计使用专业的动画制作工具Adobe After Effects来实现,使动画实现更加方便,动画效果也更好;
- 前端可以方便的调用动画,并对动画进行控制,减少前端动画工作量;
- 设计制作动画,前端展现动画,专业人做专业事,分工合理;
- 卖家秀即买家秀,还原程度百分之百;
- 使用lottie方案,json文件大小会比gif文件小很多,性能也会更好。
原理:
在Adobe After Effects中,动画是由一个一个的图层组成的,在相应的图层上面添加一些变换(例如:缩放、移动等),这变成为了动画。 lottie-web提供了很多操控动画的 方法 和 事件,基本可以满足对动画进行控制的需求。
play: 播放动画
stop: 停止播放动画
pause: 暂停动画
goToAndStop: 跳到某一帧动画,并停止
setDirection: 设置播放方向
setSpeed: 设置播放速度
onComplete: 动画播放完成触发
onLoopComplete: 当前循环播放完成触发
onEnterFrame: 播放一帧动画的时候触发
onSegmentStart: 开始播放一个动画片段的时候触发
使用示例:实现一个扑克翻牌抽奖
1. 点击按钮出现翻牌动画:
动画由Lottie配置loadAnimation信息,包括作用的容器container用refs获取、
路径path为ui提供的json文件(内容为动画本身,包括素材图片的移动缩放等)通过cdn上传到云端、
渲染方式设为svg优化页面性能、
开启自动播放autoPlay、无需循环播放loop
2. 控制动画播放的时机,在合适的时候关闭动画,展现抽奖结果(弹框显示)。动画弹框均作用于一个盒子,通常会将该触发挂载到顶层有子组件调用。
<div ref="pokersLottie" />
import lottie from 'lottie-web';
let animation;
export default {
data() {
return {
visible: false, // 弹窗展示状态
awardImg:
"https://4gimg.map.qq.com/test/f44ae635a21c7dd7f34fa6e668c41dfd.png",
popType: "login",
labelText: "送你",
goldCount: 100,
popShow: true, // 弹窗内容展示
lottieShow: false, // 动画展示状态
};
},
methods: {
/**
* 弹窗展示
* @param params.awardImg 奖品图片
* @param params.popType 弹窗类型
* @param params.labelText 文本
* @param params.goldCount 金币数量
*/
init(params = {}) {
this.awardImg = params.awardImg;
this.popType = params.popType;
this.labelText = params.labelText;
this.goldCount = params.goldCount;
this.visible = true;
if (params.popType === "award") {
this.popShow = false; // 点击之后弹框先不展示
this.lottieShow = true; // 先展示动画
this.lottieLoad({
// 重点配置
animationOptions: {
container: this.$refs.pokersLottie,
path: "https://qqmap-1251316161.file.myqcloud.com/fe-static/mapActivity/hlddz/poker/data.json",
renderer: "svg",
autoPlay: true,
loop: false,
},
});
setTimeout(() => {
this.lottieShow = false; // 1.5秒后关闭动画
this.popShow = true; // 再展示弹框内容
this.$refs.pokersLottie.innerHTML = "";
}, 1500);
}
},
/**
* 动画预加载
* @interface
* @param {Object} animationOptions - 自定义动画选项
* @param {Function} onDataReady - 资源加载结束钩子
* @param {Function} onComplete - 动画完成加载钩子
*/
lottieLoad({ animationOptions = {}, onDataReady, onComplete } = {}) {
const options = Object.assign({}, animationOptions);
animation = lottie.loadAnimation(options);
animation.addEventListener("data_ready", () => {
console.log("[lottieView][load] data_ready.");
onDataReady && onDataReady();
});
animation.addEventListener("complete", () => {
console.log("[lottieView][load] complete.");
onComplete && onComplete();
});
},
},
};
// 点击抽奖的盒子
<div
v-image.normal="AthenaData.pokers"
class="pokers"
@click="reportLottery"
/>
// 抽奖回调
methods: {
async reportLottery() {
const container = getAthenaContainer();
// 检查环境是否就绪
if (!checkConditionReady(container.main)) return;
if (this.goldCount < 100) return this.$mps.toast('金币不足,做任务获取更多金币');
if (this.actInfoData?.data?.lottery?.lottery_infos?.length) {
const lotteryInfoTemp = this.actInfoData.data.lottery.lottery_infos.filter(item => item.id === '19')[0];
const loading = this.$mps.toast({
text: '正在加载...',
type: 'loading',
autoDismiss: false,
interactive: false,
});
// 向后端发抽奖请求
const res = await fetchLottery({
game_id: Number(lotteryInfoTemp.id),
access_token: '',
});
if (res) {
// 获取活动信息,刷新按钮
const container = getAthenaContainer();
fetchActInfo({}, container.main);
}
setTimeout(() => {
loading.close();
}, 800);
}
},
}