复杂帧动画之移动端video采坑实现

在企鹅辅导品牌页中,我们需要实现一个动画如下:

页面滚动到动画区域,播放动画, 对应动画部分如下:

帧动画当前的实现有以下几种方式:

GIF 动画
大家比较熟悉的图片格式

lottie
Airbnb 开源项目,通过解析 AE 动画为 json 数据,支持跨平台的动画效果解决方案;lottie 在辅导中已经有实际应用,使用过的同学都表示对其实现效果和开发速度表示称赞和推荐,如果你还不了解 lottie, 推荐 lottie 系列学习文章,请戳我

APNG (Animated Portable Network Graphics)
基于 PNG 格式扩展的一种动画格式,增加了对动画图像的支持,其诞生是为了替代老旧的 GIF 格式,但部分浏览器不支持,需要考虑兼容;

HTML video 元素
GIF 动画适用于处理色彩简单、动效简单的动画,如 logo 、 icon 图这样的小图动画,在上面需要实现的动画中明显细节比较多,区域也比较大,考虑到质量 GIF 排除在外

在使用哪种方式实现该动画上,结合同事 @ajaxchen 的调研结论:

lottie
在设计师通过 AE 制作了动画之后,通过 AE 插件 bodymovin 将动画导出 json 给到我们前端开发,在使用这段 json 数据中,我们引入了 lottie-web 脚本来解析这段 json 数据渲染成为SVG / canvas 动画,效果如下图, 左图为用 lottie 实现,右图为我我们的目标实现效果

可以看到实现还是存在着差异,颜色、数字倾斜度、虚线的透视都没有达到预期,于是放弃lottie 的使用,但这并不否定 lottie 在实现其它动画的优秀效果

APNG
在对设计师给到的分段的动画帧图片压缩之后,其实现结果 apng 大小高达 29M,webp 格式 17M, 如此庞大的体积,且实现清晰度达不到预期,也只能放弃该方式;由于 APNG 在一些浏览器上不支持,在实现时需引入 apng-canvas 将 apng 转化为 canvas;

createJS
在我将 ISUX 上的文章《你离高效制作动画只差一篇文章的距离》发送给我们的设计小哥

之后,他如此回复我

HTML video
在上面尝试无果之后,我的同事@zzbozheng 向我展示了一个 lol 的页面,神奇,居然是用video来实现!我怎么就没想到!

查看 video 标签的兼容性,无论是我们品牌页的 PC 版还是移动 web 端,兼容性都可以满足我们的需求

设计小哥哥给到的动画 MP4 视频大小是 350k, 350k对比几十兆简直就是轻量,查了一番 video 的自动播放实现,有一些坑,跟设计师小哥哥也沟通了一番综合考虑之后毅然踩上了 video 的坑

video 标签有对应的事件方法, 可查阅文档

下面是在移动端 web 使用 video 过程中的采坑总结:

video 在 safari 和桌面端 chrome 中可能无法自动播放
这里的自动播放,无论是 video 标签的 autoplay 属性还是通过 js 自动调用 video 的 play 方法都是自动播放

桌面端 chrome 自动播放主要受制于 autoplay policy ,遵循对应的策略则可以自动播放,这主要考量于用户的体验;因为使用muted(静音)属性可以允许自动播放, 我们的动画本来就是没有声音的,所以在 video 标签中加上 muted 属性

IOS 视频自动全屏播放
查阅资料,video 标签添加两个属性即可小屏播放

有些安卓浏览器无法自动播放,touch 事件也无法触发播放
video 标签的 play 方法返回一个 promise,可通过 promise 来检测到 video 是否可自动播放

video.play()
.then(() => {
// play success
})
.catch( err => {
// auto play fail
})
当 catch 到 error 时,只能启用兼容方案,设计小哥哥给了我几张帧图片,让我渐隐渐现实现图片播放。

渐隐渐现效果

然而!在华为荣耀 8 的微信里面,我发现了个诡异的问题,视频没有播放,同时 video.play 没有 catch 到 error,而是正常的执行到了 then 方法,也就是说 play 方法返回成功,然而视频实际没有播放,这,这, 这, 是在欺骗我的感情!

无奈之下, 针对安卓的微信端,视频全部启用兼容模式(几张图片渐隐渐现)

论安卓浏览器的各种诡异表现
oppo 机视频播放自动悬浮置顶
img

video 控制条无法隐藏
视频无法控制地自动全屏播放

我:”设计小哥哥,这我无能为力

设计: “找出所有对应的机型和浏览器,对这些不支持的浏览器使用兼容模式播放动画

我:”这所有的机型实在难以控制和全部覆盖到…

设计: “那就先对所有的安卓都使用兼容模式吧,后面对此优化

于是就这样干掉了所有的安卓 video

ios QQ 浏览器视频播放完毕,展示推荐视频

这个 video 我是设置了循环播放的,硬生生 QQ 浏览器就在视频播放完毕后展示推荐视频,并且停止了我的循环播放,这让我的页面显的有点 low, 这明显是不仁道的,尝试无果之后,于是我咨询 QQ 浏览器的同事帮忙这个问题, 他让我在 video 标签上加上这个属性,即可使用系统播放器,而拒绝被拦截植入推荐视屏, 感谢@eddiecmchen 提供的意见

mtt-playsinline=”true“
设计师导出的视频背景色与提供的色彩有色差
这在不同 PC 设备中存在差异,例如 MAC 与 windows , 在移动端暂时还没发现,但是可以发现视频在移动端展示与 PC 上展示的色彩差异

至此附上实现的部分代码块,项目使用 react 技术栈

++this.catchVideoErrorCount;

// 通过点击和scroll后都无法播放视屏,使用兼容性方案
if (this.catchVideoErrorCount >= 2) {
this.setState({
isVideoCanAutoPlay: false,
});
}
});
}
}
};
最后总结:

移动端 web 对于 video 自动播放的兼容性是在太差,尤其安卓,一些浏览器对 video 标签进行拦截,并以自己的方式实现,或是悬浮置顶播放,或是两个视屏播放冲突,或是控制条无法隐藏,或是播放默认全屏,如果用其它方式可以实现动画尽量还是用其它方式
对于 video 的自动播放,考虑一些浏览器限制必须通过用户交互才能使用,如果视屏是在第一屏则有点难度,还是需要用户通过点击才能播放,如果不是第一屏则可通过 touch 事件来触发,毕竟用户下拉滚动还是会触发 touch 事件
video 的 play 方法返回的 promise 存在华为荣耀8 微信里返回 play 成功,但是却没有播放视频

http://www.5gwanglu.com/a/dongcha/390.html
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:muxilin131420 备注:入群;或加QQ群:729884609