前端动效讲解与实战
本文将从各个角度来对动画整个体系进行分类,并且介绍各种前端动画的实现方法,后我们将总结在实际开发中的各个场景的动画选择方案。
一、背景
前端动画场景需求多
对众多动画场景的技术实现方案选择上比较模糊
各动画方案的优劣及适用场景认识模糊
现有动画库太多,不知道选哪个
主流动画库的适用场景认识模糊
下面首先让我们从各个角度来对动画整个体系进行分类,让我们清晰的了解动画整个体系。
二、分类
2.1 用途角度
首先我们从动画的用途或者说是业务的角度来进行区分,将我们平时的动画分为展示型动画和交互型动画。
2.1.1 展示型动画
类似于一张GIF图,或者一段视频。比如在开启宝箱的时候,我们会加入一个切场过渡动画,来替代原有的生硬等待结果。
展示型动画在实际使用的场景中,实现的方法很多,比如用GIF图,canvas,CSS3动画等,但是终输出的结果是不带有交互的,也就是从动画起始状态到结束状态一气呵成,这个过程用户可以感知,但是无法参与。
2.1.2 交互型动画
用户自已参与的,对于交互性动画而言,我们可以在动画播放的某个时间节点触发相应的操作,进而让用户参与到其中,常见的例子红包雨,不仅仅能提升用户的体验,还能提升我们的产品的多元性。
然而交互性动画经常面临的一个问题就是,通过原生代码实现交互动画是很复杂的,同时性能和兼容性是不得不认真考虑的问题,比较好的解决方案还是寻求相关的框架。
2.2 绘制技术角度
不管采用什么方式来制作动画,终呈现到前端页面的无非是以下三种形式:
- Canvas
- div
- SVG
PS:为了简单也可以用视频,但除非动画的播放场景固定,不然移动端视频在不同app、不同机型、不同系统的播放显示都不太一样,容易踩不少坑。
2.2.1 不同绘制技术的性能差异
Canvas
- 效率高、性能好、可控性高,只能处理位图,内存占用恒定
- 依赖分辨率
- 不支持事件处理器
- 弱的文本渲染能力
- 能够以 .png 或 .jpg 格式保存结果图像
- 适合图像密集型的游戏,其中的许多对象会被频繁重绘
div
- 包括CSS控制的DOM动画、JS控制的DOM动画
- 比较适合简单的数量较少的复杂度较低的动画
SVG
- 处理矢量图,不失真
- 不依赖分辨率
- 支持事件处理器
- 适合带有大型渲染区域的应用程序(比如谷歌地图)
- 复杂度高会减慢渲染速度(任何过度使用 DOM 的应用都不快)
- 不适合游戏应用
2.2.2 Canvas和SVG比较
一句话总结:都是2D做图,svg是矢量图,canvas是位图。canvas 是逐像素进行渲染的,适合游戏。
SVG
- SVG绘制的是矢量图,缩放不影响显示,所以适合带有大型渲染区域的应用程序(比如谷歌地图)
- SVG 是一种使用 XML 描述 2D 图形的语言。
- SVG 基于 XML,这意味着 SVG DOM 中的每个元素都是可用的。您可以为某个元素附加 JavaScript 事件处理器。
- 在 SVG 中,每个被绘制的图形均被视为对象。如果 SVG 对象的属性发生变化,那么浏览器能够自动重现图形。
Canvas
- Canvas 通过 JavaScript 来绘制 2D 图形。
- Canvas 是逐像素进行渲染的。
- 在 Canvas 中,一旦图形被绘制完成,它就不会继续得到浏览器的关注。如果其位置发生变化,那么整个场景也需要重新绘制,包括任何或许已被图形覆盖的对象。
- Canvas只占用一个DOM节点,在做一些烟*花、飘雪等运动元素很多的动画时,会比CSS/SVG性能好。
性能比较
- 一般情况下,随着屏幕大小的增大,canvas将开始降级,因为需要绘制更多的像素。
- 随着屏幕上的对象数目增多,SVG 将开始降级,因为我们正不断将这些对象添加到 DOM 中。
- 这些度量不一定准确,以下方面的不同一定会引起变化:实现和平台、是否使用完全硬件加速的图形,以及 JavaScript 引擎的速度。
2.3 动画类型角度
前端动效开发,首先应该确定的是
动画用途->确认动画类型->确认绘制技术->确认动画的实现方式。
虽然终呈现动画的载体(绘制技术)就三种,但实现动画的方式却很多,得从动画类型出发讨论动画的实现方式:
(1)逐帧动画(序列帧动画)
- GIF实现
- CSS实现(animation)
- JS+DOM实现
- JS+canvas实现
(2)补间动画(Tween动画\关键帧动画)
- CSS实现(transition、animation等)使用一些缓动函数
- JS实现
(3)SVG动画
- 使用 XML 格式定义图形
- 可以用AI等SVG编辑工具生成SVG图片后,配合anime.js、GSAP等现有库进行动画制作
(4)骨骼动画
- 一般采用Spine、DragonBones等工具导出相应资源图片和JSON动画配置资源后使用。
(5)3D动画
- DOM操作用CSS 3D实现。(perspective属性、css3d-engine)
- 场景搭建用webGL(Three.js等)
- 3D模型动画用Blender或maya等制作完成后导出使用
2.3.1 逐帧动画(序列帧动画)
逐帧动画是在时间帧上逐帧绘制帧内容,由于是一帧一帧的画,所以逐帧动画具有非常大的灵活性,几乎可以表现任何想表现的内容。
由于逐帧动画的帧序列内容不一样,不仅增加制作负担而且终输出的文件量也很大,但它的优势也很明显:因为它相似与电影播放模式,很适合于表演很细腻的动画,如3D效果、人物或动物急剧转身等等效果。
所以逐帧动画的实现核心是什么,就是将我们的这些静态的图片进行快速的循环播放,形成了一个动态的动画效果。这就是帧动画。
2.3.1.1 GIF实现
我们可以将帧动画导出成GIF图,GIF图会连续播放,无法暂停,它往往用来实现小细节动画,成本较低、使用方便。但其缺点也是很明显的:
- 画质上,GIF 支持颜色少(大256色)、Alpha 透明度支持差,图像锯齿毛边比较严重;
- 交互上,不能直接控制播放、暂停、播放次数,灵活性差;
- 性能上,GIF 会引起页面周期性的绘画,性能较差。
2.3.1.2 CSS实现
CSS3帧动画是我们今天需要重点介绍的方案,核心的是利用CSS3中Animation动画,确切的说是使用animation-timing-function 的阶梯函数 steps(number_of_steps, direction) 来实现逐帧动画的连续播放。
帧动画的实现原理是不断切换视觉内图片内容,利用视觉滞留生理现象来实现连续播放的动画效果,下面我们来介绍制作CSS3帧动画的几种方案。
(1)连续切换动画图片地址src(不推荐)
我们将图片放到元素的背景中(background-image),通过更改 background-image 的值实现帧的切换。但是这种方式会有以下几个缺点,所以该方案不推荐。
- 多张图片会带来多个 HTTP 请求
- 每张图片加载会造成图片切换时的闪烁
- 不利于文件的管理
(2)连续切换雪碧图位置(推荐)我们将所有的帧动画图片合并成一张雪碧图,通过改变 background-position 的值来实现动画帧切换。分两步进行:
步骤一:
将动画帧合并为雪碧图,雪碧图的要求可以看上面素材准备,比如下面这张帧动画雪碧图,共20帧。
相关文章