聊一聊前端动画的种类,以及动画的触发方式有哪些?
版本速递 3076 2025-10-30 09:45:26

引言

动画在前端开发中扮演着重要的角色。它不仅可以提升用户体验,还可以使界面更加生动和有趣。在这篇文章中,我们将深入探讨前端动画的各种实现方式,包括 CSS 动画、JavaScript 动画、SVG 动画等。我们还将讨论一些触发动画的方式和动画在用户体验中的最佳实践。

前端动画分类

CSS 动画

CSS Transition CSS 过渡,属于补间动画,即设置关键帧的初始状态,然后在另一个关键帧改变这个状态,比如大小、颜色、透明度等,浏览器将自动根据二者之间帧的值创建的动画。CSS Animation CSS 动画,可以理解是 CSS Transition 的加强版,它既可以实现 补间动画 的动画效果,也可以使其以 逐帧动画 的方式进行绘制。 SVG 动画

SVG 动画用于矢量图形,提供了高质量的动画效果,常用于图标和图形动画。可以使用 SMIL 在SVG中定义动画。同样的也可以使用css或者js来控制svg动画。 Canvas 动画

通过结合使用 requestAnimationFrame、路径和变换等技术对画布的元素进行擦除和重新绘制,可以实现复杂的动画效果。另外Canvas还可以用于绘制复杂的背景或静态内容,从而减少每帧的绘制工作量。可以参考我的一篇关于canvas制作动画的文章:用Canvas绘制一个高可配置的圆形进度条 JS 动画

setTimeout / setInterval / requestAnimationFrame setTimeout 和 setInterval 这两个 API 设定的时间会因为浏览器当前工作负载而有所偏差,而且无法与浏览器的绘制帧保持同步。所以才有了 与浏览器的绘制帧同步 的原生 API requestAnimationFrame,以取代 setTimeout 和 setInterval 实现动画。

Web Animations API 浏览器动画 API,通过 JavaScript 操作。这些 API 被设计成 CSS Transition 和 CSS Animation 的接口,很容易通过 JS 的方式实现 CSS 动画,它是对动画化的支持最有效的方式之一。

css 动画

css过渡动画 transition

注意

由于浏览器是根据样式差异化的两帧自动计算并过渡,所以 transition 只支持可识别中间值的属性 (如大小、颜色、位置、透明度等),而如 display 属性则不支持。

语法定义

transition-property: 指定哪个或哪些 CSS 属性用于过渡。只有指定的属性才会在过渡中发生动画,其他属性仍如通常那样瞬间变化。

transition-duration: 指定过渡的时长。你可以为所有属性指定一个值,或者指定多个值,或者为每个属性指定不同的时长。

transition-timing-function: 指定一个缓动函数,定义属性值怎么变化。常见的缓动函数是一个三次贝塞尔曲线 ( cubic-bezier(, , , ) )。当然也可以选择关键字

linear:cubic-bezier(0.0, 0.0, 1.0, 1.0)ease:cubic-bezier(0.25, 0.1, 0.25, 1.0)ease-in:cubic-bezier(0.42, 0.0, 1.0, 1.0)ease-out:cubic-bezier(0.0, 0.0, 0.58, 1.0)ease-in-out: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: [, , ...];

// 如果任意属性值列表的长度比其他属性值列表要短,则其中的值会重复使用以便匹配

// 如果某个属性的值列表长于 `transition-property` 的属性,则将被截短

css过渡动画 触发方式

1. 伪类触发(:hover、:focus、:active等)

.button {

background-color: blue;

transition: background-color 0.3s ease;

}

.button:hover {

background-color: red;

}

2. 类名切换(通过JS动态切换类名来触发过渡效果)

3. 属性变化

4. 伪元素触发(通过伪元素如::before、::after的状态变化来触发过渡效果。)

css动画 animation

注意

CSS Animation 具备了对 关键帧和循环次数 的自定义能力。CSS Animation 在实现像 CSS Transition 补间动画 效果时,还可以在起始帧和结束帧之间自定义中间帧,使得动画更加平滑过渡的同时,对动画有了更好的控制和自定义能力。

语法定义

先创建一个带名称的 @keyframes 规则,以便后续使用 animation-name 属性将动画同其关键帧声明进行匹配。每个规则包含多个关键帧,也就是一段样式块语句,每个关键帧有一个百分比值作为名称,代表在动画进行中,在哪个阶段触发这个帧所包含的样式。

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 规则来显示该元素。这是默认值forwards:目标将保留由执行期间遇到的最后一个关键帧计算值。backwards:动画将在应用于目标时立即应用第一个关键帧中定义的值。 animation-timing-function:设置动画在每个周期的持续时间内如何进行,主要是如下两种函数: cubic-bezier 三次贝塞尔曲线 ( cubic-bezier(, , , ) ),以实现 补间动画 效果。

steps 是一个分段的阶跃函数,,以实现 逐帧动画。n 相当于单次动画的帧数,每帧动画的时间是均等的 (steps(n, )),其中 jumpterm (默认值 end) 含义如下:

jump-start:在起始位置阶跃,n=2 ⇒ 50% 100%; (100 / 2)jump-end:在结束位置阶跃, n=4 ⇒ 0% 25% 50% 75%; (100 / 4)jump-none:起止位置均无跳跃,n=5 ⇒ 0% 25% 50% 75% 100%; (100 / 4)jump-both:起止位置均有跳跃 n=3 ⇒ 25% 50% 75%; (100 / 4)start:等同 jump-startend:等同 jump-endstep-start:等同 steps(1, jump-start)step-end:等同 steps(1, jump-end)

/* 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);

css animation 动画触发方式

和css transition 触发动画方式相似

此外还可以增加一个图层,专门用于制作动画效果。

例如:鼠标在点击按钮时,会有涟漪动画。

// 涟漪动画定义

@keyframes ripple {

0% {

transform: scale(0);

opacity: 1;

}

to {

transform: scale(4);

opacity: 0;

}

}

// 图层动画 css

.ripple {

position: absolute;

border-radius: 50%;

background: rgba(8, 7, 7, 0.2);

pointer-events: none;

animation: ripple 0.6s linear;

}

// 制作动画 这样每次点击按钮 就会生成动画,动画结束便销毁动画元素

const makeAnimate = (e: React.MouseEvent) => {

const dom = e.currentTarget;

const rect = dom.getBoundingClientRect();

const x = e.clientX - rect.left;

const y = e.clientY - rect.top;

const size = 100;

const ripple = document.createElement('span');

ripple.classList.add('ripple');

ripple.style.width = `${size}px`;

ripple.style.height = `${size}px`;

ripple.style.left = `${x - size / 2}px`;

ripple.style.top = `${y - size / 2}px`;

dom.appendChild(ripple);

ripple.addEventListener('animationend', () => {

ripple.remove();

});

};

svg 动画

常用的 SMIL 动画元素

:用于动画化单个属性。:用于动画化变换属性,如旋转、缩放、平移等。:用于沿着路径动画化元素。(路径动画):用于在指定时间点设置属性值。

svg 描边动画

SVG动画的路径实现主要依赖属性:stroke(描边)和 fill(填充)。

stroke:定义svg的轮廓线。常用css属性有: stroke-dasharray(描边的样式),stroke-dashoffset(起始位置),stroke-color(描边的颜色),stroke-opacity(描边的透明度),stroke-linecap(描边端点形状)等。fill:定义svg内部颜色或图案 ,常用css属性有fill-opacity(定义填充的透明度), fill-rule(定义填充规则)等。

stroke-dasharray (定义虚线的长度和间隔)

提供一个奇数或偶数数列,其中数与数之间用逗号或空格隔开,用来指定短划线和缺口的长度,并重复。 如果是偶数数列,则一个表示短线长度,一个表示缺口长度。 如果是奇数数列,将奇数数列复制一个变成偶数数列,然后按照短线,缺口的顺序绘制。

(偶数数列) stroke-dasharray="5, 5" x1="10" y1="10" x2="190" y2="10"表示从坐标(10,10)到(200,10)这条水平线上,短划线和缺口都为5个px

(奇数数列) stroke-dasharray="20 10 5" x1="10" y1="10" x2="190" y2="10"表示从坐标(10,10)到(200,10)这条水平线上,短划线和缺口按照20 10 5 20 10 5的顺序排列。

stroke-dashoffset (定义虚线的起始位置)

stroke-dashoffset 属性用于指定路径开始的距离(正值向左偏移,负值向右偏移)

描边动画示例:svg描边动画

js 动画

setTimeout / setInterval API

设定定时器,通过周期性的触发重复执行绘制动画的函数,来实现 “逐帧动画” 的效果。

优势

具有很好的浏览器兼容性 劣势

只能接近设备屏幕刷新率,无法做到和浏览器同步,所以可能会存在卡顿、丢帧、抖动的现象由于浏览器单线程机制,存在队列中回调函数被阻塞的可能,所以无法保证每一次调用的时间间隔都相同,某次回调可能会被跳过,导致跳帧。

requestAnimationFrame API

为了弥补 setTimeout / setInterval 在动画方面的不足,浏览器提供了为动画而生的 API,它可以让 DOM 动画、Canvas 动画、 SVG 动画等有一个统一的刷新机制,随着浏览器的屏幕刷新,统一绘制动画帧。

let id = null

// 动画函数

const draw = () => {

/* 动画绘制... */

}

const start = () => {

draw()

cancelAnimationFrame(id)

id = requestAnimationFrame(start)

}

const stop = () => { cancelAnimationFrame(id) }

优势

由系统来决定回调函数的执行时机, 它能保证回调函数在屏幕每一次的刷新间隔中只被执行一次, 这样就不会引起丢帧现象, 也不会导致动画出现卡顿的问题。在运行时浏览器会自动优化方法的调用,并且如果页面不是激活状态下的话,动画会自动暂停,有效节省了CPU的开销。 不足

同 setTimeout/setInterval 一样,它是以逐帧动画的方式进行绘制,无法做到像 CSS 动画,让游览器自动根据两帧之间的差异创建插值,以实现补间动画的过渡效果。

Web Animations API

requestAnimationFrame、setTimeout/setInterval 都是以逐帧绘制的方式实现动画, 而 Animations API 不仅可以 “逐帧动画”,还可以实现 “补间动画” 的效果。CSS 动画有一定的局限性,需要事先预设动画样式,而且无法与 JS 进行交互。相比之下,Animations API 可以随时定义并使用动画,自然是更加灵活方便。

参考文档: https://developer.mozilla.org/zh-CN/docs/Web/API/Web_Animations_API

语法示例:

const element = document.getElementById("container");

const animation = element.animate(

[

{ transform: "translateY(0%)" },

{ transform: "translateY(100%)" },

],

{ duration: 3000, fill: "forwards" }

);

代码示例:Web Animations API 动画

关于Flip动画

浏览器计算位置很快,绘制可能很慢。利用浏览器强大的计算能力,获取动画的起止状态,接着单独开启一个线程做动画。这样触发布局更新的操作,只会发生在一帧时间内,剩下的动画跑在单独的线程上,会更流畅。

介绍下FLIP 。

F 代表 First,也就是动画的开始状态。L 代表 Last,代表动画结束状态。I 代表 Invert,也就是状态反转,使用 transform 等属性,创建单独的图层,并将元素状态反转回去。P 代表 Play,播放动画。

示例代码:

其中,在初始帧中,应用逆变换(translate 和 scale),将元素从其最终状态逆变换到初始状态。

最后一帧 transform: "none" 的作用是将元素的变换属性重置为其最终状态。具体来说,transform: "none" 表示不应用任何变换,这意味着元素将恢复到由 CSS 设置的最终位置和大小。

FLIP Animation Example

Copyright © 2022 GXLC网游资讯网-新版本速递_限时活动_礼包兑换 All Rights Reserved.