To C 业务场景下的 Web 页面,经常会有炫酷复杂的动效需求。在一个有限的项目排期下,选择合适的动效解决方案:既可以符合设计师的动效要求,又可以用最少的时间完成任务,但往往对前端工程师来说是一个巨大的挑战。
有的同学可能会问:Web 动画不就是用 CSS 写吗?transition
、transfrom
、 animation
、keyframes
这些 CSS 属性和用法,我烂熟于心。如果动画再复杂点,那就继续用上 JavaScript
动画库,比如 Tween.js、Gsap、JQuery 的animate方法,等等。
的确,“CSS + JavaScript” 已经可以满足绝大部分的场景。但是,随着动效复杂度的上升,我们需要手写的代码量也在剧增。而且,对于动画的细节呈现,设计师往往比我们有着更高的要求:当我们耗时耗力手写完一个效果后,往往还要继续花费大量时间和设计师进行沟通,以便对动画的细节进行调整。
上图的扭蛋机动画,如果是前端工程师手撸代码(CSS + JavaScript)来实现的话,弊端很明显:开发周期长。动画的各处细节需要和设计师沟通,例如设置运动速度的transition-timing-function
、animation-timing-function
属性值,都需要设计师给出我们具体的贝塞尔曲线,以保证动画播放的流畅。
那有没有一种更高效的方案,让设计师制作完动画效果,我们就可以拿来即用呢?
这就是本篇将要讨论的几种更高效的 web 动效方案。
Gif / APNG / WebP
最简单的方案,当然就是让设计师直接导出一张动图。
Gif
说到动图,我们首先想到的肯定是 Gif:
上图就是一张 Gif 动图,可以看见,非常方便就能播放动画了。
<!-- 直接img标签引入图片即可播放 -->
<img src="https://img.zcool.cn/community/01584659ccc891a801218e18e4097e.gif" />
优点:简单方便,兼容性好,支持透明。
缺点:
- 仅支持 8bit 的索引色,也就是说只有 256 个颜色,会出现颜色失真,白边锯齿的情况,并且体积较大,不支持半透明。
- 只能循环播放,无法精准控制动画。(可以通过 libgif-js 第三方库进行播放和暂停。)
Apng
APNG 是一种可动画 PNG 格式,也称为“动态 PNG”。需要注意的是,APNG 格式的图片,后缀名依旧是.png
。
上图就是一张 APNG 格式的动图。
<!-- 直接img标签引入图片即可播放 -->
<img src="https://www.zhangxinxu.com/study/202109/chip.png" />
优点:支持半透明,颜色还原度更高,且体积较小。
缺点:
- 兼容性相比 Gif 差点,浏览器如果不支持 APNG,则会以普通的 PNG 图片显示(静止在第一帧)。可以使用 apng-canvas 来兼容 APNG 的播放。
- 只能循环播放,但是可以通过 apng-js 转成 Canvas 绘制,来播放和暂停动画。
WebP
WebP 是一种由谷歌开发的现代图像格式,旨在提供更高的压缩率和更好的图像质量,同时保持较小的文件大小。它还支持透明度和动画。
上图就是一张 WebP 格式的动图。
<!-- 直接img标签引入图片即可播放 -->
<img src="https://mathiasbynens.be/demo/animated-webp" />
优点:完美支持无损图像,同等质量下体积更小。
缺点:
- 兼容性相比 Gif 差点。
- 只能循环播放,但是可以通过 freezeframe.js 转成 Canvas 绘制,来播放和暂停动画。
帧动画
设计师提供一系列的序列帧图片,前端通过连续循环切换这些图片,实现动画的播放。
实现帧动画的方式有很多,可以详细参考《CSS3动画之逐帧动画》文章。
优点:自由控制播放、暂停、帧速率、动画时长。
缺点:动画帧率较高时需要请求大量的图片资源,弱网状态下可能导致动画卡顿。
Video 视频
透明背景 MP4
各大直播软件中的全屏礼物特效,业界有 VAP 和 YYEVA 方案:可以播放带透明背景的 MP4。但这些方案对于 web 的支持度不太友好,只适合在端内进行尝试。
非透明背景 MP4
由于普通的 MP4 格式的视频是带背景色的,因此全屏的背景动画比较适合此种方案。
设计师需要提供给我们一个全屏的静音视频,PC 端建议 19201080 尺寸,移动端建议 7501750 尺寸。
PC 端
PC 端对于视频自动播放限制不多,只需要默认静音即可:
<div class='video-container'>
<video
autoplay
loop
muted
preload="auto"
src='https://media-cdn-zspms.kurogame.com/pnswebsite/website2.0/video/1679328000000/c9s9mf24e3fotwqyqk-1679393034357.mp4'>
</video>
</div>
.video-container {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
video {
width: 100%;
height: 100%;
object-fit: cover;
}
}
移动端
移动端对于视频自动播放限制严格:
- iOS 10+ 才开始支持视频自动播放,但是需要视频静音并且有
playsinline
属性。 - Android 手机上不同的浏览器,对于
video
标签的处理不尽相同,很可能被原生控件拦截。
因此建议采用 Canvas 绘制视频:业界已经有了 jsmpeg 的成熟方案,支持 TS 格式,MPEG1
编码的视频播放。
jsmpeg 播放视频
首先我们将设计师给我们的 MP4 格式视频转码成 MPEG1 编码的 TS 格式。
可以通过网站 Convertio 进行转码(注意编解码器一定要选择 MPEG1
):
当然,我们也可以通过 FFmpeg 自行转码:
# 使用ffmpeg命令行转换mp4至ts (如果画质不行,可以自行调整画质 3000k 5000k)
ffmpeg -i soruce.mp4 -f mpegts -codec:v mpeg1video -an -b:v 3000k output.ts
# 使用ffmpeg命令行截图poster封面
ffmpeg -i soruce.mp4 -ss 00:00:00.000 -vframes 1 poster.png
得到了 TS 格式的视频后,前端通过 jsmpeg 即可进行播放:
<div class="video-container">
<canvas class="canvas-view"></canvas>
</div>
<button id="btn1">暂停</button>
<button id="btn2">播放</button>
<button id="btn3">跳到2s</button>
.canvas-view {
width: 50%;
}
const player = new JSMpeg.Player('./output.ts', {
canvas: document.querySelector('.canvas-view'),
autoplay: true,
disableWebAssembly: true,
onPlay(player){
console.log('onPlay', player);
},
});
const btn1 = document.getElementById('btn1');
const btn2 = document.getElementById('btn2');
const btn3 = document.getElementById('btn3');
btn1.addEventListener('click', () => {
player.pause();
});
btn2.addEventListener('click', () => {
player.play();
});
btn3.addEventListener('click', () => {
player.currentTime = 2;
});
优点:几乎任何的动画效果都能实现。
缺点:
- 不带透明通道,需要全屏尺寸。
- 交互能力较弱,弱网状态下视频播放可能卡顿。
骨骼动画
《代号·世界》官网中运用了大量的骨骼动画。
上图中人物衣服和头发的飘动,就是典型的骨骼动画。
Spine 和 DragonBones 是两款比较常见的骨骼动画制作软件,在手游中被大量应用,同时它也支持在 web 端播放。
DragonBones 由于不再维护(白鹭科技 已倒闭),所以不建议新项目使用。
Spine动画,则通过 pixi-spine ,就可以很容易地集成进 web 项目里。
Live2d
Live2D 是一种应用于电子游戏的绘图渲染技术,由日本 Cybernoids 公司开发。和 Spine 类似,也可以制作动作细腻的人物动效。手游中的角色立绘就经常使用 Live2d 制作。同时,虚拟主播的二次元模型也常常使用该技术。
上图中,人物随着鼠标的移动,身体各处都在运动,就是使用的 Live2d 技术。
由于官网的web sdk比较难用,这里推荐使用第三方的pixi-live2d-display进行项目集成
SVGA
SVGA 是 YY 直播团队开源的一种跨平台的动画格式,同时兼容 iOS / Android / Web。动画设计师专注动画设计,通过工具输出 svga 动画文件,提供给开发工程师在集成 svga player 之后直接使用。
一般用在直播间的礼物特效。
通过官方的 Web-Player 即可在 web 端播放。
Lottie
Airbnb 开源的可应用于 Android、iOS、Web、React Native 和 Windows 动画库,本质上是一套跨平台的动画解决方案。
通过 AE 的 Bodymovin 插件将设计师做的动画导出成一套定义好的 JSON 文件,之后再通过 Lottie 各端的库就可以实现动画效果,动画还原度 100%。
开头介绍的扭蛋机动画,正是使用 Lottie 实现的。
SVGA与Lottie最本质的区别在于代码对动画过程记录的方式,Lottie基本上是按照我们在AE当中的关键帧及缓动的结合形式去记录动画,而SVGA则是通过记录我们每一个图层每一个时间上的动画状态,从而省去对缓动值的计算。
因此可以把Lottie看成是补间动画,SVGA看成是帧动画。
游戏引擎
最后, 我们也可以使用Oasis、Cocos、 Unity等更专业的游戏引擎,为项目提供更真实的物理效果。
总结
本文主要介绍了几种高效的动效解决方案,旨在解放前端工程师在动效还原上的开发时间和效率,让更专业的人做更专业的事:
- 动效设计师负责动效的实现和输出
- 前端工程师负责动效的播放和交互
本系列教程专门介绍 Lottie 的使用方法和高级技巧,后续的篇章将会带领大家进入 Lottie 的学习之旅。