积分签到动画-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 动画库来实现:
- 动画库体积都不小,在轻量级页面引入动画库,感觉有点大。
- 网页需要兼容 IE11、国产手机各类浏览器,若动画库出现兼容性问题,解决难度也蛮大的。
- 从控制力度上,JavaScript 的
element.animate()
的兼容性不是很理想,用作个人研究可以,但并未达到用在正式环境的程度。 - 这里还有点小心思,我个人想完成 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金币上扬、变色
金币变色上扬的动画其实蛮简单的,就是两层数字,深灰色的覆盖在橙色上。灰色数字位置上移且消失,露出下方的黄色数字
而这里要着重说明的是 CSS keyframes 动画是可以简写的。
1
2
1
0
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金币-购物车效果
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》