积分签到动画-CSS3 Animation版

精美小巧的动画,让你耳目一新

  • 产品、交互、UI:了解动画基本原理,与前端如何配合
  • 前端:了解常见动画的实现方式,与设计师配合将动画效果做的更好
  • 测试:了解动画原理,在测试时有章可循

在大前端日益流行的情况下,前端工程师越来越注重 JavaScript 的深入学习,而只是完成了页面 UI 布局和功能实现,却在用户体验提升方面的能力有所欠缺。而增强用户体验的方法除了更美观的用户界面,那就还有恰到好处的页面交互动画了。页面交互动画可以吸引用户的目光,可以在发生人机交互时带来小惊喜,给人以满足感。

本文中会包含一个复合型动画,其项目背景为在 CCtalk 平台签到时会赚取 C 币。在签到加 C 币的过程中,包含了 C 币的变化、天数的变化等交互动画。

这里,先将一个复合型动画进行拆解,明确每个动画元素的效果,再逐一讲解每个动画的实现思路、核心源码,还会讲解相关的其他知识点。

本文源码 | 动画文档

国外大牛 Josh W Comeau 的文章:《An Interactive Guide to CSS Transitions

Link to this heading
动画元素与时间轴分析

将上述动画按照难度由易到难进行粗略排列:

  • 金币旋转(含对勾):使用逐帧动画来完成
  • 签到按钮:渐变色动画,基于opacity控制按钮
  • 色块背景变化:单色动画,通过改变背景色
  • 金币数字飘动:位移动画,使用translateY来完成
  • 金币总数、签到天数的增加:数字翻滚动画,涉及到 X 轴、Y 轴的变化
  • 金币飘动:类似”加入购物车“的效果,有JS计算位置和 CSS3 Animation 两种方案

在设计师给出的演示动画中,共40帧,一秒为12帧,平均一帧为0.083秒。

通常有12、24、30、60、120帧,这些大部分都是3的倍数。

而在计算机的时间概念中,1s=1000ms,并不能被3整除,所以我将动画从3.333秒改为4秒,也就是一秒10帧。

Link to this heading
为何不使用 Lottie 动画库来实现:

  1. 动画库体积都不小,在轻量级页面引入动画库,感觉有点大。
  2. 网页需要兼容 IE11、国产手机各类浏览器,若动画库出现兼容性问题,解决难度也蛮大的。
  3. 从控制力度上,JavaScript 的element.animate()的兼容性不是很理想,用作个人研究可以,但并未达到用在正式环境的程度。
  4. 这里还有点小心思,我个人想完成 CSS3 动画的积累,并且还要从 320~768px 来完成适配,使用 CSS3 动画对我来说是更好的选择。

更具体的分析,请参考《动画:从 AE 到 Web》。

Link to this heading
动画效果解析

基于逐帧动画实现,关键性的为steps(1)来完成。

Link to this heading
核心动画代码

编译后

Link to this heading
逐帧动画图片制作方法

雪碧图

上面的逐帧动画所需雪碧图是基于雪碧图工具实现的。

关于更多逐帧动画的文章细节,请参考《CSS3动画之逐帧动画 》。

Link to this heading
为何用 CSS3 逐帧动画替代 Gif 动画?

Gif 动画在网页应用中长盛不衰,其优点很明显,那就是制作简单、使用方便,那有木有缺点呢?

  • 色彩空间只有 256 色,比 jpeg、png 少很多,画质也差了很多
  • 只支持 0 或 100 的透明度。设计师经常会在 Icon 边缘加入的投影,可能会引起毛边
  • 体积比 png 帧序列的图可能还要大。比如,相同的 40 帧动画图,gif 体积为 142 kb,而 png 经过 tinypng 压缩后为 42 kb
  • 没有可控性。 Gif 图是预先导出好的动画序列,但 CSS 逐帧动画是由 CSS animation 来控制播放进度
进度时间
进度时间

签到天数的背景是从淡灰色(#f2f3f7)变为淡黄色(#FFF1A9),通过改变背景色可以轻松完成。

这里面最关键就是动画变化曲线了,这里使用了自定义的贝塞尔曲线来完成。

观察下图中的”立即签到“按钮,我们可以看到,按钮背景色为渐变色,并且边缘有外投影。

立即签到

注意点:

  • 背景图上的linear-gradient并不支持transition动画
  • 外投影box-shadow虽然有动画效果,但也挺影响渲染性能的。

由此,我们需要写两个按钮,通过改变透明度来完成动画效果。

立即签到

Link to this heading
核心动画源码

Link to this heading
金币上扬、变色

金币变色上扬的动画其实蛮简单的,就是两层数字,深灰色的覆盖在橙色上。灰色数字位置上移且消失,露出下方的黄色数字

+5
+5

而这里要着重说明的是 CSS keyframes 动画是可以简写的。

 
1
 
2
8
1
8
0
2
4
显示辅助线,查看动画细节
底数:
加数:

原理:翻转数值计算,计算原数字和增长后的数字,并完成前后数字的对位排列

  • 同位数字,上下翻转
  • 若位置上的数字不等位,则上下翻转且横向宽度变化。
  • 从末尾到首位依次延迟翻转

Link to this heading
问题1:字体宽度不定

CSS Transition 动画中需要的是确认的宽度,宽度无法从0px变成auto的。

而数字从0px变成实际宽度,数字宽度不一。如数字1的宽度为12px时,数字0的宽度为16px。

方案1:改用等宽字体。

方案2:使用16px为统一宽度,并且数字居中显示。

Link to this heading
问题2:同等位数的数字翻转,如899到900

1、数字偏移使用translate3d(0, -40px, 0)偏移位置,动画曲线为cubic-bezier(.68,-.04,.26,1.55)

2、数字从后往前,以此添加动画延迟 transition-delay

Link to this heading
问题3 :不等位数的数字翻转,如882到12104

1、使用空格补齐相差的位数,使用 \u00A0 来代替 nbsp; 来补齐。

2、宽度变化从 "0px" 变成 “17px”。此处为何不使用width: auto;呢,因为 CSS Transition 的转场动画并不支持auto动画。

Link to this heading
金币-购物车效果

我的C币

Link to this heading
问题1:抛物线动画分拆

X 轴匀速运动

进度时间

Y轴变速运动

进度时间

Link to this heading
问题2:计算起始坐标和运动的长方形

通过getBoundingClientRect()可以获取起始点和目标点的位置数据,从而计算出所需抛物线的长方形数据(宽高、坐标)

Link to this heading
问题3:为何不使用 js计算物体的抛物线位置

在 《H5、小程序飞入购物车(抛物线绘制运动轨迹点)?》一文中,使用抛物线公式实时计算x轴和y轴的位置,使用setTimeout去更改 this.state 上的值。

产生的问题有:

  • 频繁更换this.state的值
  • 有多个金币,性能问题更严重

本篇 CSS3 动画分析文章,从基础的颜色变化、到逐帧动画、到比较复杂动画的分拆设计,循序渐进地讲解了各种基础动画的实现思路。

当然,如果想深入了解 CSS3 动画的基础概念以及深度实践,可以阅读以下来自京东凹凸实验室的文章:

也可以阅读国外大牛 Josh W Comeau 的文章:《An Interactive Guide to CSS Transitions