在微信小程序上,控制与播放动画(GIF、LOTTIE)的坑坑与洼洼

由于项目上,需要在小程序上,实现一些动画效果,反馈用户操作。

最初的方案,是采用GIF,但发现有一些不好的用户使用体验,即:

  1. GIF是自动循环播放的,无法与用户操作保持很好的同步反馈
  2. GIF文件体积太大,对于低网速手机用户,加载效果不好;

问了AI,提议使用 LOTTIE ,于是,开启了踩坑之路。

大多数在微信小程序上,使用 LOTTIE ,都是从 npm install lottie-miniprogram 开始。但 lottie-miniprogram 内部依赖了 lottie-web,而 lottie-web 是使用动态创建组件的特性,而微信小程序是禁用此特性的。

因此,大多数情况下,从官网下载的demo,在微信开发者工具上,一跑,可以显示 LOTTIE 动画,但是跑到真机上,调试,就出不来了。而且在控制台会看到提示“发现 Lottie 动态创建 canvas 组件,但小程序不支持动态创建组件,接下来可能会出现异常”。

很显然,要对 lottie-miniprogram 做一下兼容处理,于是,创造轮子,不如找轮子。问了 AI,说是可以用 uniapp 的插件:c-lottie

https://ext.dcloud.net.cn/plugin?id=11085

感谢作者,示例写的也比较规范,清晰。试跑了一下,DEMO果然可以跑在苹果手机和安卓手机。

于是,将手头几个现成的 GIF 动画,转成 LOTTIE.json ,一开始是通过 lottiefiles 官网转换,但它只能免费转换5次,明显不够用。

将 GIF 转成 LOTTIE.json 后,实测又发现以下问题:

  1. 通过 lottiefiles 官网默认转换的 JSON 文件,体积竟然比 GIF 还大(无法接受!);
  2. 转换后的 LOTTIE.json 文件,在苹果微信上,可以正常显示动画,但在安卓微信上,跑了,显示空白;

于是,反复对比,发现,默认转换后的 JSON 文件里,图片文件的base64编码格式是 WEBP 的。秒懂,果断将图片重新编码为 PNG的base64格式,重新保存为 LOTTIE.json 文件,目前,安卓微信和苹果微信,都可以正常显示动画了。

在微信小程序上,控制与播放动画(GIF、LOTTIE)的坑坑与洼洼

总结:

  1. 要在微信小程序上,显示 LOTTIE 动画,提议直接用 uniapp 的 c-lottie 插件;
  2. 手头如果有现成 GIF 文件,需要转换成 LOTTIE.json ,不提议用官网 lottiefiles,改用 python库( pip3 install lottie )来转换,性价比会更容易接受;
  3. 通过 python-lottie 转换的 LOTTIE.json 文件,里面的 “layers” 节点的 “ip” “op” 参数,可能会不连续帧(出现跳跃),需要手工修正,保存一下(不处理的话,也看不出来,就是不好通过代码控制播放速度和帧,如果需要暂停的话)。

在微信小程序上,控制与播放动画(GIF、LOTTIE)的坑坑与洼洼

  1. 转换后的 LOTTIE.json 文件,需要确保里面的图片编码为 PNG-base64 的(可以思考通过 omggif js库,提取 GIF 文件中的图片帧,然后另存为 PNG 图片);
  2. 可以对 PNG文件压缩一下, 再base64(可以思考通过 sharp js库,压缩 PNG 图片);

参考代码段

///////////////////////////////////////////

将 GIF 中的图片帧,另存为 PNG 格式

// b. 使用pngjs将RGBA像素编码为PNG二进制

const png = new PNG({

width,

height,

inputColorType: 6, // 6表明RGBA格式(对应pngjs的colorType)

inputHasAlpha: true

});

// 将pixels(Uint8Array)复制到png的数据缓冲区

png.data.set(pixels);

// c. 将PNG数据转为Buffer,再转为Base64

const pngBuffer = PNG.sync.write(png); // 同步生成PNG的Buffer

///////////////////////////////////////////

压缩 PNG

// 2. 直接将 Buffer 传入 sharp() 构造处理对象

const compressedBuffer = await sharp(pngBuffer)

// .resize(500) // 缩小宽度到 500px(高度按比例自适应)

.png({

palette: true, // 启用调色板

colours: 16, // 限制最大颜色数(1-256,根据图片复杂度调整)

compressionLevel: 9,

}) // 压缩为 PNG

// .toFile('output_from_buffer.png'); // 输出到文件

.toBuffer(); // 输出为 Buffer(而非文件)

///////////////////////////////////////////

编码为 PNG base64

const base64 = `data:image/png;base64,${compressedBuffer.toString('base64')}`;

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
接单达人的头像 - 鹿快
评论 共1条

请登录后发表评论