由于用户越来越注重 Web应用 的使用体验,随之而来的是 Web应用 需要提供了更加完善的 Web 动画 效果来实现以平滑的状态贯穿于用户的整个使用过程中。现在,这已经是司空见惯了,用户潜意识是希望可以获得更快的反馈响应和更友好的用户界面。
屏幕刷新率
设备显示器每秒绘制新图像的次数,其单位为赫兹 (Hz)。目前大多数设备为 60Hz。卡顿
每个帧的预算时间仅比 16毫秒
多一点(1秒/ 60 = 16.6毫秒
)。如果浏览器无法在这一帧内完成工作,则帧率将下降,可能导致跳帧,内容会在屏幕上抖动。此现象通常称为卡顿。跳帧
假如浏览器动画分别在 16ms, 32ms, 48ms时分别切帧。等到了 32ms,浏览器其他任务还未完成,没有执行动画切帧。等到恢复动画切帧时,浏览器到了 48ms 的动画切帧。浏览器直接从16ms 处的画面 跳转到 48ms 处的画面,则发生了跳帧。在了解了上述几个概念后,我们再看 Web 动画本质是元素的外观样式或布局位置随着浏览器的逐帧绘制,以平滑的状态完成变化 。
目前浏览器实现动画的方式有如下两种,本篇将主要讲解第二种 CSS 动画
。
JS 动画
setTimeout
和 setInterval
这两个API。但是这两个 API 设定的时间会因为浏览器当前工作负载而有所偏差,而且无法与浏览器的绘制帧保持同步。所以才有了 与浏览器的绘制帧同步 的原生 API requestAnimationFrame
,以取代 setTimeout
和 setInterval
实现动画。CSS Transition
和 CSS Animation
的接口,所以可以很容易通过 JS 的方式实现 CSS 动画,它是对动画化的支持最有效的方式之一。CSS 动画
(本篇主题)
CSS Transition
的加强版,它既可以实现 补间动画 的动画效果,也可以使其以 逐帧动画 的方式进行绘制。就如之前所说,它属于 补间动画,需要提供起始和结束两个关键帧,浏览器才能够完成样式差异比对并计算出对应的过渡动画。所以它有两个特点:
transition
一般不会生效transition
只支持可识别中间值的属性 (如大小、颜色、位置、透明度等),而如 display 属性则不支持。CSS 过渡通常使用简写属性 transition
来定义,这是最好的方式。既可以避免属性值列表长度不一,也节省了在 CSS 代码上调试的时间。当然也可以用下面子属性来定义过渡的各部分:
transition-property
: 指定哪个或哪些 CSS 属性用于过渡。只有指定的属性才会在过渡中发生动画,其他属性仍如通常那样瞬间变化。
transition-duration
: 指定过渡的时长。你可以为所有属性指定一个值,或者指定多个值,或者为每个属性指定不同的时长。
transition-timing-function
: 指定一个缓动函数,定义属性值怎么变化。常见的缓动函数是一个三次贝塞尔曲线 ( cubic-bezier(
)。当然也可以选择关键字
cubic-bezier(0.0, 0.0, 1.0, 1.0)
cubic-bezier(0.25, 0.1, 0.25, 1.0)
cubic-bezier(0.42, 0.0, 1.0, 1.0)
cubic-bezier(0.0, 0.0, 0.58, 1.0)
cubic-bezier(0.42, 0.0, 0.58, 1.0)
transition-delay
: 指定延迟,即属性开始变化时与过渡开始发生时之间的时长。
/* 单条 简写形式 */
transition:
;
/* 多条 简写形式 */
transition:
,
,
...;
/* 单条 子属性形式 */
transition-property: ;
transition-duration: ;
transition-timing-function: ;
transition-delay: ;
/* 多条 子属性形式 */
transition-property: [, , ...];
transition-duration: [, , ...];
transition-timing-function: [, , ...];
transition-delay: [, , ...];
div {
opacity: 1;
}
div:hover {
opacity: 0.5;
transition: opacity, 3s;
}
div:hover {
transition-property: opacity, left, top, height;
transition-duration: 3s, 5s;
}
/* 等同于下面样式声明 */
div:hover {
transition-property: opacity, left, top, height;
transition-duration: 3s, 5s, 3s, 5s;
}
transition-property
的属性,则将被截短 div:hover {
transition-property: opacity, left;
transition-duration: 3s, 5s, 2s, 1s;
}
/* 等同于下面样式声明 */
div:hover {
transition-property: opacity, left;
transition-duration: 3s, 5s;
}
你可以监听 CSS 过渡的开始和结束
transitionrun
: CSS 过渡动画触发 (在任何延迟之前)transitionstart
: CSS 过渡动画触发 (在任何延迟之后)transitionend
: CSS 过渡动画结束事件监听回调函数会接收一个 TransitionEvent
对象,除了具有一般的 Event
对象外,还有两个额外属性:
propertyName
一个字符串,表示过渡完成的 CSS 属性的名称。elapsedTime
一个浮点数,表示在事件发生时,过渡已经运行了多少秒。CSS Animation 才算是真正意义上的 CSS3 动画,它具备了对 关键帧和循环次数 的自定义能力。与 CSS Transition 相比较,有如下 CSS 过渡 所不具备的特性:
animation-timing-function: steps()
属性实现了 CSS Transition 无法具备的 逐帧动画 效果@keyframes
中的 to
),在首屏渲染时,它默认会以指定元素在动画开始时刻的样式作为起始关键帧,并结合 to
定义的结束关键帧和指定元素的 animation
其他参数来完成补间动画的计算和动画帧的绘制。创建 CSS 动画序列,需要使用 animation
属性或 其子属性 animation-*
,该属性允许配置动画时间、时长以及其他动画细节,但该属性不能配置动画的实际表现,动画的实际表现是由 @keyframes
规则实现。
@keyframe
使用关键帧,先创建一个带名称的 @keyframes
规则,以便后续使用 animation-name
属性将动画同其关键帧声明进行匹配。每个规则包含多个关键帧,也就是一段样式块语句,每个关键帧有一个百分比值作为名称,代表在动画进行中,在哪个阶段触发这个帧所包含的样式。
css
复制代码
@keyframes slidein {
from {
transform: translateX(0%);
}
to {
transform: translateX(100%);
}
}
/* 等效于下面 @keyframes 规则的定义 */
@keyframes slidein {
0% {
transform: translateX(0%);
}
100% {
transform: translateX(100%);
}
}
注意事项:
animation-*
CSS 动画通常使用 animation
属性来定义,它是 animation-name,animation-duration, animation-timing-function,animation-delay,animation-iteration-count,animation-direction,animation-fill-mode 和 animation-play-state 等一系列属性的简写形式。
animation-name
:指定一个或多个 @keyframes 的名称,描述了要应用于元素的动画。多个 @keyframes 以逗号分隔的名称列表的形式指定。
animation-duration
:设置动画完成一个动画周期所需的时间,需要指定单位,如 1s
、500ms
。
animation-delay
:指定执行动画之前的等待时间。动画可以稍后开始、立即从开头开始、立即在动画中途播放 (如 -1s
) 。其中 -1s
意思是动画立即从 1s 处开始。
animation-iteration-count
:设置动画序列在停止前应播放的次数,有效值 0
、正整数、正小数、无限循环 infinite
。
animation-direction
:设置动画是正向播放 normal
、反向播放 reverse
、正向交替播放 alternate
、反向交替播放 alternate-reverse
。
animation-play-state
:设置动画是运行还是暂停,有效值 running
、paused
。
animation-fill-mode
:设置 CSS 动画在执行之前和之后如何将样式应用于其目标,有效值如下:
none
:当动画未执行时,动画将不会将任何样式应用于目标,而是已经赋予给该元素的 CSS 规则来显示该元素。这是默认值
both
:动画将遵循 forwards
和 backwards
的规则,从而在两个方向上扩展动画属性
forwards
:目标将保留由执行期间遇到的最后一个关键帧计算值。最后关键帧取决于 animation-direction
和 animation-iteration-count
:
animation-direction | animation-iteration-count | last keyframe |
---|---|---|
normal |
even or odd | 100% |
reverse |
even or odd | 0% |
alternate |
even | 0% |
alternate |
odd | 100% |
alternate-reverse |
even | 100% |
alternate-reverse |
odd | 0% |
backwards
:动画将在应用于目标时立即应用第一个关键帧中定义的值,并在 delay
期间保留此值。第一个关键帧取决于 animation-direction
值:
animation-direction | first keyframe |
---|---|
normal or alternate |
0% |
reverse or alternate-reverse |
100% |
animation-timing-function
:设置动画在每个周期的持续时间内如何进行,主要是如下两种函数:
cubic-bezier
三次贝塞尔曲线 ( cubic-bezier(
),以实现 补间动画 效果。
cubic-bezier(0.0, 0.0, 1.0, 1.0)
cubic-bezier(0.25, 0.1, 0.25, 1.0)
cubic-bezier(0.42, 0.0, 1.0, 1.0)
cubic-bezier(0.0, 0.0, 0.58, 1.0)
cubic-bezier(0.42, 0.0, 0.58, 1.0)
steps
是一个分段的阶跃函数,,以实现 逐帧动画。n 相当于单次动画的帧数,每帧动画的时间是均等的 (steps(n,
),其中 jumpterm
含义如下:
n=2 ⇒ 50% 100%; (100 / 2)
n=4 ⇒ 0% 25% 50% 75%; (100 / 4)
n=5 ⇒ 0% 25% 50% 75% 100%; (100 / 4)
n=3 ⇒ 25% 50% 75%; (100 / 4)
steps
函数动画示意图如下(输入为时间进度,输出为动画进度)
/* animation 声明样式顺序 */
/* animation-duration */
/* animation-easing-function */
/* animation-delay */
/* animation-iteration-count */
/* animation-direction */
/* animation-fill-mode */
/* animation-play-state */
/* animation-name */
animation: 3s ease-in 1s 2 reverse both paused slidein;
/* animation - duration | easing-function | delay | name */
animation: 3s linear 1s slidein;
/* more animations - duration | easing-function | delay | name */
animation: 3s linear slidein, 3s ease-out 5s slideout;
/* animation-name */
animation-name: none;
animation-name: animate1;
animation-name: animate1, animate2;
/* animation-timing-function */
animation-timing-function: ease;
animation-timing-function: step-start;
animation-timing-function: cubic-bezier(0.1, 0.7, 1, 0.1);
animation-timing-function: ease, step-start, cubic-bezier(0.1, 0.7, 1, 0.1);
/* ...... */
p {
animation: 3s infinite alternate slidein;
}
@keyframes slidein {
0% {
margin-left: 100%;
width: 300%;
}
100% {
margin-left: 0%;
width: 100%;
}
}
p {
animation-duration: 3s;
animation-name: slidein;
animation-iteration-count: infinite;
animation-direction: alternate;
}
@keyframes slidein {
0% {
margin-left: 100%;
width: 300%;
}
100% {
margin-left: 0%;
width: 100%;
}
}
animation-range
:设置动画附件范围沿其时间轴的开始和结束。animation-timeline
:指定用于控制 CSS 动画进度的时间轴。animation-composition
:指定当多个动画同时影响同一属性时要使用的复合操作。你可以监听 CSS 动画的开始和结束
animationstart
animation-delay
延时,事件会在延迟时效过后立即触发。为负数的延时时长会致使事件被触发时事件的 elapsedTime
属性值等于该时长的绝对值animationiteration
animationend
事件同时发生animationend
animationcancel
事件监听回调函数会接收一个 AnimationEvent
对象,除了具有一般的 Event
对象外,还有额外属性:
animationName
一个字符串,表示过渡完成的 CSS 动画的名称。pseudoElement
一个字符串,如果动画作用于伪元素上,则该属性为伪元素名称elapsedTime
一个浮点数,表示在事件发生时,过渡已经运行了多少秒。完整项目附件:点此下载