image.png

动画是一种通过定时拍摄一系列多个静止的固态图像(帧)以一定频率连续变化、运动(播放)的速度(如每秒16张)而导致肉眼的视觉残象产生的错觉——而误以为图画或物体(画面)活动的作品。

前端(DOM)动画实现方式大致分为下面两种:

  • CSS动画 - 通过设置CSS提供的动画属性来实现动画的效果,其主要包括两种形式的动画CSS Animation和CSS Transitions,其都是基于关键帧的动画(本文)。
  • 纯JS实现 - 使用RAF函数,在浏览器的每一帧改变DOM元素的各种属性(位置、颜色、宽度等等)来达到画面连续变化的效果,这种方式不使用动画API实现。
  • WAAPI实现 - Web Animation API 是由浏览器提供的动画接口,相当于浏览器开放底层的动画能力给开发者使用(),通过JS来调用该API、控制动画的播放过程。

关键帧(Key Frame)

对于动画直觉的感受,每一帧都需要一幅画面,假如60帧,那么就是60幅画面,像早期的动画片,都是由动画师一帧一帧的手绘出来,其成本可想而知是非常高的,效率也比较低下的。

image.png

“手绘每一帧”就相当于我们前端需要设置每一帧的动画是怎么样,显然这也是不合理的。因此就有人想出,不需要知道动画每一帧的是怎么样,我们只需要定义一段动画其中几个关键的画面,那么中间的画面通过插值的方式来自动生成,这样就可以大大的提高效率,动画中设置的关键画面,称为关键帧。设置关键帧制作的动画,称之为关键帧动画

CSS过渡动画(Transition)

CSS Transition(过渡动画),提供了一种在更改 CSS 属性时控制动画速度的方法。其可以让属性变化成为一个持续一段时间的过程,而不是立即生效的。比如,将一个元素的颜色从白色改为黑色,通常这个改变是立即生效的,使用 CSS transitions 后该元素的颜色将逐渐从白色变为黑色,按照一定的曲线速率变化。

过渡动画的特点:

  • 从开始状态过渡到结束状态,并不会循环播放,可以理解为是一次性的动画。
  • 只需要定义需要触发过渡动画的属性,开始和结束状态的判定并非事前定义,而是在页面css属性变更过程中发生变化的时候由浏览器自动判断。

在CSS中,可以通过以下属性来定义过渡动画:

  • transition: 这个属性是下面四个属性(property, duration, timing function, delay)的简写形式
  • transition-proprety: 触发过渡动画的CSS属性,并非所有的CSS属性都可以触发,具体哪些属性可以触发可以参考这个列表
  • transition-duration: 过渡动画持续的时间,可以秒(s)、毫秒(ms)为单位,比如 1s、0.5s、200ms 等等
  • transition-timing-function: 在持续时间(比如2s)内,初始状态值到结束状态值的过程中,每一帧变化的值的速率的控制由这个函数确定,比如线性(linear)、缓动(ease),其中缓动函数有多种多样的,具体可参考:https://easings.net/
  • transition-delay: 过渡动画播放的延迟时间,比如 1s 则表示1秒后再开始播放过渡动画
  1. .element {
  2. /* property | duration | timing function | delay */
  3. transition: color 2s ease-out 1s;
  4. }
  5. /* 相当于 */
  6. .element {
  7. transition-property: color;
  8. transition-duration: 2s;
  9. transition-timing-function: ease-out;
  10. transition-delay: 1s;
  11. }

CSS动画(CSS Animation)

CSS动画本质是关键帧动画,通过设置关键帧的属性(比如透明度、位置等等)、持续时间、重复次数、如何重复来进行控制,那么相隔持续时间帧之间的各帧的属性都通过浏览器插值自动生成。某种程度上说, 上述 CSS TransitionCSS Animations(@keyframe) 的一个功能子集。

定义CSS动画的属性:

  • animation: 简写形式,可以把以下8个属性的值按照顺序写在这一个属性中
  • animation-name: 使用 @keyframes 定义的关键帧动画名字
  • animation-duration: 设置动画完成一次循环的持续时间,单位可以是 mss
  • animation-timing-function: 控制动画补帧的函数,一般有线性 linear 和缓动 ease ,其中缓动函数有多种多样的,具体可参考:https://easings.net/
  • animation-delay: 动画开始播放的延迟时间
  • animation-direction: 动画播放的方向
    • normal: 每次动画循环结束,动画重置到起点重新开始
    • alternate:
    • reverse:
    • alternate-reverse:
  • animation-iteration-count: 动画循环播放的次数
  • animation-fill-mode: sets which values are applied before/after the animation.For example, you can set the last state of the animation to remain on screen, or you can set it to switch back to before when the animation began.
  • animation-play-state: 播放状态,可以设置为 pause(暂停),running(运行)
  1. .element {
  2. /* name | duration | timing func | delay | direction | iter count | fill mode | play-state | */
  3. animation: stretch 1.5s ease-out 0s alternate infinite none running;
  4. }
  5. /* 相当于 */
  6. .element {
  7. animation-name: stretch;
  8. animation-duration: 1.5s;
  9. animation-timing-function: ease-out;
  10. animation-delay: 0s;
  11. animation-direction: alternate;
  12. animation-iteration-count: infinite;
  13. animation-fill-mode: none;
  14. animation-play-state: running;
  15. }

关键帧(@keyframe):定义 CSS 动画中间帧
通过设置动画播放过程中,0 → 100% 的过程中,可以设置任意百分比的时候CSS的属性值。
当然并非所有的CSS属性值都可以被插值,无法被插值的会被忽略掉。
其中from、to0%、100%是等价:from = 0%, to = 100%

  1. @keyframes stretch {
  2. from { margin-top: 50px; }
  3. 50% { margin-top: 150px }
  4. to { margin-top: 100px; }
  5. }