最近被拉去支援紧急需求(赶在五一节假日前上线的,双休需要加班),参与到项目中才知道,开发的项目是微信小程序技术栈的。由于是临时支援,笔者也很久没开发过微信小程序了,所以挑选了相对独立,业务属性相对轻薄的模块参与。

其中有个营销活动(领红包)的弹窗动画就要用到 lottie 动画。

本文就分享一下在小程序中使用 lottie 过程中遇到的问题与解决办法。

关于 lottie

lottie 是 Airbnb 开源的一个动画库,用于在端上直接播放 AE ( Adobe After Effects)动画。

通过 bodymovin AE 插件将动画文件导出为 json 文件,lottie SDK 通过可以通过 JSON 文件直接播放动画。

具体 demos 效果可以上 LottieFiles 网站查看。

如何使用 AE 导出动画需要的JSON文件

完成 AE 软件安装后,参照 Lottie Web GitHub 官方文档 完成 bodymovin 插件的安装。

打开动画文件后,只需简单几步操作

① window 中选择 Bodymovie

② 选择需要导出的动画资源

③ 导出配置(小程序相关)

点击对应动画的设置

勾选 Glyphs 将用到的文字+字体导出为图形。

小程序里渲染不支持加载外部字体。

这个就会有 tree shake的效果,如果动画里没有用到的文字,做动态替换的时候就会不显示,后面会详细介绍到

勾选 Convert expressions to keyframes 将表达式转为关键帧,因为小程序里不支持使用 eval 等动态执行脚本的能力。

修改完成后点击Save保存配置。

④ 渲染导出 JSON 文件

最后点击 Render 按钮,导出 JSON 文件。

导出文件如下,data.json 文件就是我们需要的 JSON 文件,images 里存储的就是播放要用到的图片文件。

小程序中使用

可以使用小程序官方封装的 lottie-miniprogram 库。

快速验证的话可以打开微信开发者工具,在点击 demo代码片段 进行创建。

① 安装依赖

npm install --save lottie-miniprogram

② 使用

tip:开发者工具中验证的话,渲染模式需要选择 webview ,Skyline 目前还不支持调试 canvas

index.wxml

<canvas id="lottie-canvas" type="2d"></canvas>

index.js

import lottie from 'lottie-miniprogram'

Page({
onReady() {
this.createSelectorQuery().select('#lottie-canvas').node((res) => {
// 取得 canvas 节点
const canvas = res[0].node // 设置 cavnas 画布尺寸
canvas.width = 600
canvas.height = 600 lottie.setup(canvas) const context = canvas.getContext('2d')
const lottieInstance = lottie.loadAnimation({
loop: true, // 循环播放
autoplay: true, // 自动播放
// 本地使用 http-server 启动服务后,指定本地资源地址
path: 'http://127.0.0.1:8080/lottie-demo-sources/data.json', // 通过http 制定json资源路径 // 也可以用下面这种方式,直接传入 lottie json内容
// (需要动态替换文案就需要用到这种方式)
// animationData: {/* lottie json 格式内容 */},
// 静态资源目录,通常与 animationData 配合使用
// assetsPath: 'http://127.0.0.1:8080/lottie-demo-sources/images/', rendererSettings: {
context,
},
})
}).exec()
}
})

我这个 demo 的效果(网上找的动画素材)如下。

问题&解决

下面介绍在实际业务接入使用中遇到的一些问题和解决办法。

expression 表达式

报错信息如下,这是遇到的第一个问题(也是上面导出配置中有特别说明的)。

细看了一下文档,有特别说明,expression 表达式特性是不支持的,因此需要再导出 JSON 文件时禁用相关特性。

解决办法:导出JSON文件时,禁用掉表达式特性即可。

当然禁用后,JSON 文件大小会有所增加。

比如我这个 demo 从 40kb 增加到了 240kb(当然动画不一样,增长的大小会有所不同。有些前后可能只有1-2kb的变化)。

模糊

由于需要全屏展示,动画文件的尺寸不确定,手动只设置 canvas 尺寸会有模糊的问题。

这个通过掘金搜索了一下就得到了 lottie动画模糊问题的解决方法

微调一下上面的代码,就可以解决模糊问题。

const canvas = res[0].node
canvas.width = 600
canvas.height = 600 // 下面是新增的代码
const dpr = wx.getSystemInfoSync().pixelRatio
canvas.width = canvas.width * dpr
canvas.height = canvas.height * dpr
context.scale(dpr, dpr) lottie.setup(canvas)

全屏动画

弹窗的动画需要全屏展示,因此需要设置 canvas 宽高为页面宽高。

index.wxss

#lottie-canvas{
position: fixed;
left: 0;
top: 0;
width: 100vw;
height: 100vh;
}

index.js,使用 wx.getSystemInfoSync 获取设备的信息

const { windowWidth, windowHeight, pixelRatio } = wx.getSystemInfoSync()
canvas.width = windowWidth * pixelRatio
canvas.height = windowHeight * pixelRatio

动态文案

由于是红包,需要动态展示金额(当然也可能是不固定内容的动态标题)。

思路可以参考这篇文章知乎: 动态修改 Lottie 中的文本

可以使用固定格式的文本 ${文本} 进行替换

// 伪代码
get('sourceUrl').then((res) => {
const jsonText = res.data
const animationData = JSON.parse(jsonText.replace('${金额}', '目标金额'))
})

比如我在 demo 里加一个文字

  • 需要展示的文本里放入 ${num} 用于替换匹配
  • 在添加一个文本藏在看不见的地方,里面写入替换后需要用到的文字(确保和上面的文本为同一种字体)

接着导出 JSON 文件。

调用方法如下

// 拉取JSON文件内容
const jsonData = await new Promise((resolve) => {
wx.request({
url: 'http://127.0.0.1:8080/json/text-replace/data.json',
success: (res) => {
resolve(res.data)
}
})
}) // 随机生成1-100元的数字,保留两位小数
const num = (Math.random() * 100).toFixed(2)
// 替换内容
const animationData = JSON.parse(
JSON.stringify(jsonData)
.replace(/\$\{num\}/g, `${num}元`)
) lottie.loadAnimation({
// 指定json内容
animationData,
// 设置依赖的图片资源位置
assetsPath: 'http://127.0.0.1:8080/json/text-replace/images/',
// ...省略其它配置
})

效果如下

style 引发的渲染错误

在 canvas 标签上设置 display控制显隐,偶现会提示渲染层错误。

<canvas style="display:{{show?'block':'none'}}" id="c1" type="2d"></canvas>

解决办法,给套了一层 view,用wx:if控制咯。

<view  wx:if="{{show}}">
<canvas id="c1" type="2d"></canvas>
</view>

iOS 播放闪退问题

现象是,非冷启动小程序的时候,动画还没播放完毕就提前结束了。

看代码log,3s的动画,播放不到 1s 就触发了 complete 事件,看现象就是一闪而逝。

const ani = lottie.loadAnimation({
// 3s 的动画
animationData,
// ...省略其它配置
}) ani.addEventListener('complete', () => {
console.log('动画播放结束')
})

解决办法

TODO:未完待续

最后

时间匆忙,介绍的不是非常的详细,感兴趣的同学可以评论区交流。

demo 完整源码见 GitHub:lottie-demo

小程序中使用 lottie 动画 | 踩坑经验分享的更多相关文章

  1. 微信小程序中scroll-view的几个坑

    微信小程序中scroll-view的几个坑 1:设置scroll-x时,却不能横向滚动,因为view是block组件,但是这里用了flex就不能滚动了(想用flex布局,请开启属性enable-fle ...

  2. 小程序中搜索文件,阅览pdf,分享文件链接,评论表情符号

    小程序中搜索文件,阅览pdf,分享文件链接,评论表情符号 https://blog.csdn.net/hotqin888/article/details/84111389 小程序中打开网页和pdf h ...

  3. 微信小程序使用pako.js的踩坑笔记

    问题 今天组长跟我们讨论了个问题,说是文章存储占用有点大,消耗宽带流量费,让我看看能不能找个方法解决一下(文章存储的是html字符串).第一反应是没什么头绪,能想到的就是将相同的字符串替换成一个标识之 ...

  4. 微信小程序使用weui扩展组件踩坑

    最近在做微信小程序,引入weui的时候踩坑了好久,这里记录一下遇到的问题. 微信官方文档给了两种weui引入方式: 通过 useExtendedLib 扩展库 的方式引入,这种方式引入的组件将不会计入 ...

  5. 微信小程序 请求签名接口超时 踩坑路。。

    我们公司一般做开发都是先用测试机的接口调试功能,等功能都调试的差不多了,再换成线上的正式接口,因为正式接口要验证签名. 这几个功能都调试的差不多了,准备换成线上正式接口了,结果却出了问题,提示请求超时 ...

  6. 微信小程序豆瓣电影项目的改造过程经验分享

    在学习微信小程序开发过程中,一部分的难点是前端逻辑的处理,也就是对前端JS的代码编辑:一部分的难点是前端界面的设计展示:本篇随笔基于一个豆瓣电影接口的小程序开源项目进行重新调整,把其中遇到的相关难点和 ...

  7. 微信小程序中实现微信支付

    最近在做微信小程序,今天刚好做到小程序里的微信支付这块,踩过不少坑,特此写个博客记录下,希望能帮到其它人吧. 我总结了一下,小程序中的微信支付和之前其它的公众号里的微信支付有两个区别,第一就是小程序必 ...

  8. 微信小程序中事件

    微信小程序中事件 一.常见的事件有 类型 触发条件 最低版本 touchstart 手指触摸动作开始 touchmove 手指触摸后移动 touchcancel 手指触摸动作被打断,如来电提醒,弹窗 ...

  9. 在微信小程序中绘制图表(part2)

    本期大纲 1.确定纵坐标的范围并绘制 2.根据真实数据绘制折线 相关阅读:在微信小程序中绘制图表(part1)在微信小程序中绘制图表(part3) 关注我的 github 项目 查看完整代码. 确定纵 ...

  10. 网页或微信小程序中使元素占满整个屏幕高度

    在项目中经常要用到一个容器元素占满屏幕高度和宽度,然后再在这个容器元素里放置其他元素. 宽度很简单就是width:100% 但是高度呢,我们知道的是height:100%必须是在父元素的高度给定了的情 ...

随机推荐

  1. 解决cv2. imread、imwrite无法读取或保存中文路径图片问题

    cv2.imwrite(filename, img) 修改为 cv2.imencode('.jpg', img)[1].tofile(filename) cv2.imread(filename, cv ...

  2. vue项目中添加水印效果

    新建js文件:例如warterMark.js 'use strict' let watermark = {} let setWatermark = (str) => { let id = '1. ...

  3. Scala 复杂分词求和(二元组)

    1 package chapter07 2 3 object Test18_ComplexWordCount { 4 def main(args: Array[String]): Unit = { 5 ...

  4. #线段树,离线#CF1000F One Occurrence

    题目 给定一个长度为\(n\)序列,\(m\)个询问,每次询问给定一个区间\([l,r]\), 如果这个区间里存在只出现一次的数,输出这个数(如果有多个就输出任意一个),没有就输出0 分析 考虑离线, ...

  5. #Every-SG#HDU 3595 GG and MM

    题目 有\(n\)个游戏,每个游戏只要能进行就必须进行, 对于每个游戏有两堆石子,每次可以将数量多的中取出小堆石子数量的整数倍, 无法操作者为负,问先手是否必胜 分析 如果单个游戏最大操作次数为奇数次 ...

  6. #位运算#CF959E Mahmoud and Ehab and the xor-MST

    题目 \(n\)个点的完全图标号为\([0,n-1]\),\(i\)和\(j\)连边权值为\(i\: xor\:j\),求MST的值 分析 考虑MST有两种解法一种是Prim一种是Kruskal,Pr ...

  7. van-cell如何使用插槽

    van-cell 是 Vant 组件库中的一个单元格组件,用于展示列表中的信息.Vant 是一个轻量.可靠的移动端 Vue 组件库. 在 Vant 中,van-cell 组件提供了多个插槽(slot) ...

  8. Tailscale 的 TLS 证书过期,网站挂了 90 分钟!

    3月7日,基于 WireGuard 的知名 VPN 厂商 Tailscale 的官方网站 tailscale.com 因 TLS 证书过期而中断服务约90分钟. 虽然影响有限,但这起事件还是在 Hac ...

  9. failed to push some refs to xxxx

    ***************ssh  秘钥上传远程仓库 1. 添加远程仓库ssh 命令   git remote add origin  git@github.com:ThreeNut/zou.gi ...

  10. 第十九篇:Django ORM外键关联关系

    一.一对多的创建 二.一对多跨表操作 三.创建多对多 四.Ajax处识 五.模板继承与导入 六.自定义分页