Open JChehe opened 6 years ago
呃~貌似好久没写文章了,感觉有点奇怪。废话不多说,但还是加点前戏吧。
不想听废话,直入主题>>
为何要写这篇文章
接下来因工作调整,应该就很少接触 H5 开发了。借此机会总结个人对动画的一些思考。
本文贴合实战,会结合笔者为数不多的开发案例进行讲解🤣。文章结尾也会提供相应文件让读者进行实践。
同一份设计稿给到不同开发者,结果可能千差万别。而结果主要由两部分体现——内在与外在。『内在』指的是代码质量、性能优化,『外在』则指的是视觉还原度和动效(交互)。
其中对于更直观的『外在』来说,视觉还原度高是前提,真正体现差距的是『动效』。因为设计师一般只给到“静态”的视觉稿,而无动画演示,更不用说提供动效搞(如 AE)了。
在这种情况下,页面的动效更多是由前端开发者自由发挥。因此对动效有钻研的同学优势尽显。我也曾问过这些同学,他们大多回答是:“多试多调”。因此,在设计师无『动效稿』提供的情况下,都需要花时间慢慢调整,以达到各方(本人、设计师、产品和需求方等)满意。若没有设计、动效等相关知识的学习与积累,恐怕是一只『没头苍蝇』。
关于动画的理论方面,笔者并没有积累,但推荐一些不错的资料(或许需要梯子)。同时也希望得到读者们的有效补充:
大多数前端开发者在设计和动效方面并没有太多积累,因而难以做出令人拍手称赞的效果。其实,这是设计师(和动效设计师)所擅长的领域。下表给出两者的对比:
从上表可看出,将『动效设计』交给设计师能显著提高效益。
而在实际工作流程上:
假设达成以上共识后,剩下的问题就是:如何还原『动效稿』?
设计师输出的动效演示
注:全文『动效稿』均基于 Adobe After Effects(简称 AE)设计。
其实,与『制造业』一样,实现方式就两种:
两者的优缺点比较:
机械代表着“未来、高效”。业界出现了很多优秀的工具,使得在浏览器渲染复杂动效成为了可能,且极大地提高了效率。
代表工具有:
可是『世界上本来就没有十全十美的东西』。机械化生产可能未必满足所有要求,生产环境上的要求就更加苛刻了。主要体现在:机械化生产导致介入难度高。若出现以下问题就比较棘手:
无论如何,『机械化』是未来,期待它早日以完美的姿态到来。
手工代表着“自定义、可控性”。无论世界如何工具化,总有一些人保持着对『手工』的热爱。
『手工』意味着从无到有的过程。需要我们参与这个过程的每一步。这也就使得我们拥有很强的自定义能力。这恰恰是『机械化』目前所不具备的特性。这也是本文重点阐述的内容。
基于 AE 手工实现 Web 动画的主要工作有两点:
Web 动画一般分为 逐帧动画 和 补间动画。
显然,对于取参操作来说,逐帧动画比补间动画的工作量要大得多,但两者操作一致。所以下面以 补间动画 Apple 为例:
打开 apple.aep 文件,AE 界面如下:
apple.aep
AE 界面
点击『信息模块』预览面板的播放按钮或拖动『时间轴模块』的 标记3 即可预览动画。
标记3
根据 CSS3 animation 属性,我们需要获取以下信息:
animation-duration
animation-timing-function
animation-delay
为了方便阐述,我们选取整个 Apple 动画中一个小圆圈(共 60 个)为代表,其余元素同理。 另外,由于该动画是一次性的,无需获取/设置动画的重复次数(animation-iteration-count)、运动方向(animation-direction)。
animation-iteration-count
animation-direction
现在我们把目光投向『图层、运动模块』的 标记1:
标记1
标记1——FPS
由上图可得,FPS 为 12,即 1 秒 12 帧, 1 帧 0.0833 秒。
由上面 Apple 动画 可看出,每个圆的延时时间(animation-delay)、缓动函数(animation-timing-function)和持续时间(animation-duration)均不相同。换句话说,每个圈都是一个独立的补间动画,所有元素组合起来才是一个完整的补间动画。
双击『标记 2』,进入编组以查看每个圆的信息。
子元素——圆
在『查看器』或『图层、运动模块』任意选中一个圆,展开其 变换 属性并单击 位置(标记1),即可在其右侧显示元素运动路径(标记2)。同时这也反映了属性的变化速率(即缓动函数(animation-timing-function),这方面会在后续详解。
变换
位置
位置 前面的时钟图标为蓝色时,代表有过渡动画。
某个圆的时间轴
结合上面知识,可从上图得出以下信息点:
因此,我们基于 CSS3 animation 实现该元素的补间动画:
<div class="circle-29"></div>
/* 默认将该园定位在第 2(或 3)关键帧的位置,以让元素默认显示屏幕内,便于开发调试。 */ .circle-29 { width: 60px; height: 60px; background-color: rgba(0, 224, 93, .7); position: absolute; left: 473px; top: 348px; border-radius: 50%; animation-name: circle29; animation-duration: 3.5s; /* 42 * (1 / 12) */ animation-delay: 0.0833s; /* 1 * (1 / 12) */ animation-fill-mode: both; animation-timing-function: ease-in-out; } @keyframes circle29 { 0% { transform: translate3d(0, 1175px, 0); } 61.90% { /* (2 * 12 + 3 - 1) / 42,注意要减去延时时间(1 帧)。下同。*/ transform: translate3d(0, 0, 0); } 64.29% { /* (2 * 12 + 4 - 1) / 42 */ transform: translate3d(0, 0, 0); } 100% { transform: translate3d(0, -1225px, 0); } }
这样就完成了某个圆的补间动画了。虽然繁琐,但省去了反复试验的时间,基本做到一次开发,各方满意的效果。
See the Pen ae2web-circle by Jc (@JChehe) on CodePen.
其余元素按照以上步骤即可完成整个动画。
假设没有动画演示和动效稿,仅凭个人感觉,编码完成一个由 60 多个元素组成的动画,简直难于上青天(对于笔者来说)。
细心的读者可能发现:如果第 1、2 关键帧和第 3、4 关键帧的缓动函数不相同时,该怎么办?
首先部分人可能对 animation-timing-function 存在误解:它是作用于整个 @keyframes 规则的。❌
@keyframes
其实缓动函数是作用于 @keyframes 规则内的关键帧。若未为关键帧指定 animation-timing-function,则从其元素取得 animation-timing-function。
更严格地说,缓动函数是应用在属性上。当关键帧有指定 animation-timing-function 时,则该缓动函数会影响该关键帧内所有属性,而每个受影响的属性,其缓动效果会结束在下一个有指定同样属性的关键帧。
举个例子:
.box { width: 100px; height: 100px; background-color: #6190e8; animation: move 2s ease both; } @keyframes move { 0% { animation-timing-function: linear; transform: translateX(0); opacity: 1; } 50% { opacity: .5; } 100% { transform: translateX(100px); opacity: 1; animation-timing-function: ease-in-out; /* 无用多余 */ } }
在 0% 关键帧中指定的 animation-timing-function: linear 会对 transform 和 opacity 属性有效。但因为 50% 关键帧未指定 transform 属性,所以 animation-timing-function: linear 对它生效至有指定 transform 属性的关键帧,即 100% 关键帧。
animation-timing-function: linear
transform
opacity
对于 opacity 属性,因为 50% 关键帧未指定 animation-timing-function,所以它会取 .box 元素上指定的 ease 缓动函数。
.box
ease
简言而之:
综上所述,可在关键帧上指定不同的缓动函数,以满足属性在各个关键帧间不同的变化速率。
细心的读者可能又发现:缓动函数碰巧是 预定义的关键字 还好,但如果是以下这种情况呢?
显然浏览器预定义的关键字无法还原这些类型的缓动函数,但浏览器提供了强大的 cubic-bezier() 方法。翻译过来就是三次贝塞尔曲线。因此,我们可以通过该方法自定义缓动函数。
cubic-bezier()
想了解贝塞尔曲线的更多知识,可阅读 《贝塞尔曲线扫盲》。
AE 时间轴 上呈现的是属性的变化路径,其未必与变化速率(即缓动函数)完全一致。因为它们的 X/Y 轴含义不同。
如上图所示,AE 是属性随着时间而变,CSS3 animation 是动画进度随着时间而变。然而属性的变化是有方向的,动画进度是永远向前的。
AE: AE 属性变化是有方向的
对应 CSS3 animation-timing-function: 动画进度永远是向前的
如上面二图所示,下图是上图的速率变化(缓动函数)。理清 AE 与 CSS3 animation 的对应关系后,剩下的问题就是:如何通过 cubic-bezier() 表示图中的 CurveA 与 CurveB。
CurveA
CurveB
也许有工具可从 AE 直接导出(欢迎读者们提供链接),但本文为了简单起见,推荐使用 Ceasar 或 Cubic-Bezier.com 这类可视化工具直接模拟生成。
因此,上述补间动画的缓动函数可表示为:
@keyframes ae2css { 0% { animation-timing-function: ease-out; } 23% { animation-timing-function: ease-in; } 50% { animation-timing-function: cubic-bezier(0.5, 0, 0.5, 1.5); } 76% { animation-timing-function: cubic-bezier(0, 0, 0, 1); } 100% { } }
本文基于实际案例总结出 AE 到 Web 动画的实现方法。相对于『无动效稿』的反复编码尝试,该方法无疑能提高效益。当然,『手工』不能胜任复杂的动画(如 SVG 的变形动画(Morphing)),并且低效。因此,业界在『机械/工具化』方面不断推陈出新,涌现出许多优秀的工具,让复杂动画在各终端上得以展现。无论如何,学习更多知识总没错!
最后,感谢你的阅读!
Apple 补间动画整体效果演示(一次性动画,请点击 "RERUN" 按钮重播):
See the Pen ae2css-apple by Jc (@JChehe) on CodePen.
呃~貌似好久没写文章了,感觉有点奇怪。废话不多说,但还是加点前戏吧。
前戏
为何要写这篇文章
接下来因工作调整,应该就很少接触 H5 开发了。借此机会总结个人对动画的一些思考。
本文贴合实战,会结合笔者为数不多的开发案例进行讲解🤣。文章结尾也会提供相应文件让读者进行实践。
为何“别人”实现的动效恰到好处?
同一份设计稿给到不同开发者,结果可能千差万别。而结果主要由两部分体现——内在与外在。『内在』指的是代码质量、性能优化,『外在』则指的是视觉还原度和动效(交互)。
其中对于更直观的『外在』来说,视觉还原度高是前提,真正体现差距的是『动效』。因为设计师一般只给到“静态”的视觉稿,而无动画演示,更不用说提供动效搞(如 AE)了。
在这种情况下,页面的动效更多是由前端开发者自由发挥。因此对动效有钻研的同学优势尽显。我也曾问过这些同学,他们大多回答是:“多试多调”。因此,在设计师无『动效稿』提供的情况下,都需要花时间慢慢调整,以达到各方(本人、设计师、产品和需求方等)满意。若没有设计、动效等相关知识的学习与积累,恐怕是一只『没头苍蝇』。
关于动画的理论方面,笔者并没有积累,但推荐一些不错的资料(或许需要梯子)。同时也希望得到读者们的有效补充:
其实可以把『锅』扔给设计师
大多数前端开发者在设计和动效方面并没有太多积累,因而难以做出令人拍手称赞的效果。其实,这是设计师(和动效设计师)所擅长的领域。下表给出两者的对比:
1. 专业度
2. 实现效率:可视化 > 编写代码
3. 沟通成本
4. 各方满意度
5. ...
从上表可看出,将『动效设计』交给设计师能显著提高效益。
而在实际工作流程上:
假设达成以上共识后,剩下的问题就是:如何还原『动效稿』?
设计师输出的动效演示
AE 到 Web 实现
其实,与『制造业』一样,实现方式就两种:
两者的优缺点比较:
机械实现
机械代表着“未来、高效”。业界出现了很多优秀的工具,使得在浏览器渲染复杂动效成为了可能,且极大地提高了效率。
代表工具有:
可是『世界上本来就没有十全十美的东西』。机械化生产可能未必满足所有要求,生产环境上的要求就更加苛刻了。主要体现在:机械化生产导致介入难度高。若出现以下问题就比较棘手:
无论如何,『机械化』是未来,期待它早日以完美的姿态到来。
手工实现
手工代表着“自定义、可控性”。无论世界如何工具化,总有一些人保持着对『手工』的热爱。
『手工』意味着从无到有的过程。需要我们参与这个过程的每一步。这也就使得我们拥有很强的自定义能力。这恰恰是『机械化』目前所不具备的特性。这也是本文重点阐述的内容。
基于 AE 手工实现 Web 动画的主要工作有两点:
如何手工取参
Web 动画一般分为 逐帧动画 和 补间动画。
显然,对于取参操作来说,逐帧动画比补间动画的工作量要大得多,但两者操作一致。所以下面以 补间动画 Apple 为例:
打开
apple.aep
文件,AE 界面如下:AE 界面
根据 CSS3 animation 属性,我们需要获取以下信息:
animation-duration
animation-timing-function
animation-delay
现在我们把目光投向『图层、运动模块』的
标记1
:标记1——FPS
由上图可得,FPS 为 12,即 1 秒 12 帧, 1 帧 0.0833 秒。
由上面 Apple 动画 可看出,每个圆的延时时间(
animation-delay
)、缓动函数(animation-timing-function
)和持续时间(animation-duration
)均不相同。换句话说,每个圈都是一个独立的补间动画,所有元素组合起来才是一个完整的补间动画。双击『标记 2』,进入编组以查看每个圆的信息。
子元素——圆
在『查看器』或『图层、运动模块』任意选中一个圆,展开其
变换
属性并单击位置
(标记1),即可在其右侧显示元素运动路径(标记2)。同时这也反映了属性的变化速率(即缓动函数(animation-timing-function
),这方面会在后续详解。某个圆的时间轴
结合上面知识,可从上图得出以下信息点:
因此,我们基于 CSS3 animation 实现该元素的补间动画:
这样就完成了某个圆的补间动画了。虽然繁琐,但省去了反复试验的时间,基本做到一次开发,各方满意的效果。
See the Pen ae2web-circle by Jc (@JChehe) on CodePen.
其余元素按照以上步骤即可完成整个动画。
假设没有动画演示和动效稿,仅凭个人感觉,编码完成一个由 60 多个元素组成的动画,简直难于上青天(对于笔者来说)。
也许你对
animation-timing-function
存在误解细心的读者可能发现:如果第 1、2 关键帧和第 3、4 关键帧的缓动函数不相同时,该怎么办?
首先部分人可能对
animation-timing-function
存在误解:它是作用于整个@keyframes
规则的。❌其实缓动函数是作用于
@keyframes
规则内的关键帧。若未为关键帧指定animation-timing-function
,则从其元素取得animation-timing-function
。更严格地说,缓动函数是应用在属性上。当关键帧有指定
animation-timing-function
时,则该缓动函数会影响该关键帧内所有属性,而每个受影响的属性,其缓动效果会结束在下一个有指定同样属性的关键帧。举个例子:
在 0% 关键帧中指定的
animation-timing-function: linear
会对transform
和opacity
属性有效。但因为 50% 关键帧未指定transform
属性,所以animation-timing-function: linear
对它生效至有指定transform
属性的关键帧,即 100% 关键帧。对于
opacity
属性,因为 50% 关键帧未指定animation-timing-function
,所以它会取.box
元素上指定的ease
缓动函数。简言而之:
综上所述,可在关键帧上指定不同的缓动函数,以满足属性在各个关键帧间不同的变化速率。
更强大的 cubic-bezier
细心的读者可能又发现:缓动函数碰巧是 预定义的关键字 还好,但如果是以下这种情况呢?
显然浏览器预定义的关键字无法还原这些类型的缓动函数,但浏览器提供了强大的
cubic-bezier()
方法。翻译过来就是三次贝塞尔曲线。因此,我们可以通过该方法自定义缓动函数。AE 时间轴 上呈现的是属性的变化路径,其未必与变化速率(即缓动函数)完全一致。因为它们的 X/Y 轴含义不同。
如上图所示,AE 是属性随着时间而变,CSS3 animation 是动画进度随着时间而变。然而属性的变化是有方向的,动画进度是永远向前的。
举个例子:
AE: AE 属性变化是有方向的
对应 CSS3
animation-timing-function
: 动画进度永远是向前的如上面二图所示,下图是上图的速率变化(缓动函数)。理清 AE 与 CSS3 animation 的对应关系后,剩下的问题就是:如何通过
cubic-bezier()
表示图中的CurveA
与CurveB
。也许有工具可从 AE 直接导出(欢迎读者们提供链接),但本文为了简单起见,推荐使用 Ceasar 或 Cubic-Bezier.com 这类可视化工具直接模拟生成。
因此,上述补间动画的缓动函数可表示为:
总结
本文基于实际案例总结出 AE 到 Web 动画的实现方法。相对于『无动效稿』的反复编码尝试,该方法无疑能提高效益。当然,『手工』不能胜任复杂的动画(如 SVG 的变形动画(Morphing)),并且低效。因此,业界在『机械/工具化』方面不断推陈出新,涌现出许多优秀的工具,让复杂动画在各终端上得以展现。无论如何,学习更多知识总没错!
最后,感谢你的阅读!
案例演示
Apple 补间动画整体效果演示(一次性动画,请点击 "RERUN" 按钮重播):
See the Pen ae2css-apple by Jc (@JChehe) on CodePen.
素材下载
参考资料