一、网页动画发展简史
GIF动画
GIF全称为“Graphics Interchange Format”,是一种基于LZW算法的连续色调无损压缩格式。
由于其文件小、无损压缩、易于播放等优点,GIF成为了网页动画的最初选择。然而,GIF动画的色彩数量和帧数有限,而且不能包含声音,因此其表现力相对有限。
Flash动画
Flash动画是一种使用Macromedia公司开发的Flash软件创建的动画。它具有以下特点:
- 基于矢量图形:Flash动画使用矢量图形,这意味着图形可以被任意缩放而不会降低图像质量。
- 插件工作方式:Flash以插件方式工作,用户可以在浏览器上安装Flash插件,快速启动和观看Flash动画。
- 流式播放技术:Flash动画采用流式播放技术,使得动画可以边下载边播放,大大减少了用户等待的时间。
- 交互式设计:Flash动画不仅具有丰富的视觉效果,还提供了交互性,使得用户可以与动画进行互动。
- 跨平台性:Flash动画可以在多种操作系统和浏览器上播放,这使得它成为一种非常流行的网络动画格式。
- 强大的功能:Flash软件提供了绘图、编辑图形、补间动画和遮罩等基本功能,使得用户可以创建出各种效果的动画。
然而,随着移动设备的普及和HTML5技术的兴起,Flash逐渐被淘汰。
JavaScript动画
随着JavaScript库如jQuery的出现,开发者开始使用JavaScript来创建更丰富的交互式动画。这些库简化了DOM操作和动画效果的实现。
HTML5/CSS3
HTML5引入了<canvas>
和<svg>
元素,提供了原生绘图功能。CSS3开始,引入了更多的动画和过渡效果。
通过使用CSS3的动画关键帧(@keyframes)、过渡(transition)等特性,可以轻松地创建各种复杂的动画效果。
同时,CSS3动画也具有更好的兼容性和性能。
WebGL
WebGL是一种基于OpenGL ES 2.0的图形渲染协议,可以在不需要任何插件的情况下在浏览器中进行3D图形渲染。通过WebGL,开发者可以创建更复杂的3D动画和交互式体验。
React和Vue动画
随着前端框架的发展,例如React和Vue,也提供了专门的动画库(如React Spring、Vue.js的过渡效果),简化了在组件级别实现动画的过程。
Web动画API
Web动画API是一组用于控制动画序列的JavaScript接口。例如Animation
、AnimationTimeline
等;它允许开发者使用JavaScript直接控制CSS动画和SVG动画。
二、原生CSS动画
动画属性(animation)
动画属性用于决定动画的播放时长、播放次数以及播放速度等。
基本语法
animation: duration | easing-function | delay | iteration-count | direction | fill-mode | play-state | name
// 实例:
animation: 3s ease-in 1s infinite reverse both running animateName;
CSS animation 属性是一个简写属性,用于设置六个动画属性:
- animation-name: 定义动画的名称,与@keyframes规则中的名称相对应。
- animation-duration: 定义动画完成一个周期所需要的时间,以秒或毫秒计。默认值为0(动画是否可见取决于animation-fill-mode 的值)。
- animation-timing-function: 定义动画的速度曲线。默认值为"ease"。
- animation-delay: 定义动画在何时开始。动画开始前的延迟时间,以秒或毫秒计。默认值为0(动画会立即开始)。
- animation-iteration-count: 定义动画应该播放的次数。默认值为1(动画将从开始播放到结束只播放一次)。
- animation-direction: 定义动画应正向播放、反向播放还是在正向和反向之间交替播放。。默认值为“normal”(动画应该正向播放)。
- animation-fill-mode:定义动画在执行之前和之后如何将样式应用于其目标。默认值为“none”(当动画未执行时,动画将不会将任何样式应用于目标)。
- animation-play-state:定义动画是运行还是暂停。默认值为“running”(当前动画正在运行)。
实例
旋转元素
动态更改元素大小及透明度
可访问代码地址查看源码实现
关键帧(@keyframes)
关键帧用于定义动画在不同阶段的状态,可以通过百分比或关键词(例如“from”和“to”)来定义动画的起始和结束状态。
基本语法
使用from(0%) 和to(100%),指定动画的开始或结束状态。
@keyframes animation-name { from {transform: translateX(0%);}to {transform: translateX(100%);}
}
使用百分比,指定动画在不同阶段需要触发的样式。
@keyframes animation-name { 0% {top: 0;left: 0;}30% {top: 50px;}68%,72% {left: 50px;}100% {top: 100px;left: 100%;}
}
实例
使用from,to定义单词“Hello”从左向右移动;使用百分比使单词"World"从右向左移动。
变换(Transform)
CSS transform
属性允许旋转,缩放,倾斜或平移给定元素。这是通过修改 CSS 视觉格式化模型的坐标空间来实现的。
基本语法
transform: none | transform-function | initial | inherit;
none
表示没有任何转换效果。transform-functions
表示一个或多个转换函数,如translate()
,rotate()
,scale()
等。initial
表示将属性设置为初始值。inherit
表示从父元素继承该属性。
transform-function
<transform-function>
属性用于对元素进行转换操作,它提供了多种转换方式,包括旋转(rotate)、缩放(scale)、移动(translate)、倾斜(skew)和矩阵变换(matrix)等。这些转换操作可以单独使用,也可以组合在一起使用,以实现更复杂的变换效果。
旋转(rotate)
使用
rotate()
函数是一种将元素围绕一个定点旋转而不变形的转换。旋转角度可以是正值(顺时针旋转)或负值(逆时针旋转)。其中,转换定点由transform-origin
属性指定,默认值是center
。
// 将元素顺时针旋转45度
transform: rotate(45deg);
缩放(scale)
使用
scale()
函数可以按指定的倍率缩放元素。当只有一个参数时,表示水平和垂直方向同时缩放该倍率;当有两个参数时,第一个参数指定水平方向的缩放倍率,第二个参数指定垂直方向的缩放倍率。
// 将元素水平方向和垂直方向同时缩小到原来的一半
transform: scale(0.5);
移动(translate)
二维平移: 使用
translate()
函数可以将元素在X轴和Y轴方向上平移指定的距离。可以使用translateX()
函数仅在X轴方向上平移元素,使用translateY()
函数仅在Y轴方向上平移元素。三维平移:如果设置三个长度值或百分比,表示分别指定 X 轴、Y 轴、Z 轴的值进行三维平移。等同于
translate3d()
函数(3D 平移)。
// 将元素在X轴方向上平移100像素,在Y轴方向上平移50像素。
transform: translate(100px, 50px);
// 将元素在X轴方向上平移100像素,在Y轴方向上平移50像素,在Z轴方向上平移20像素。
transform: translate(100px, 50px, 20px);
translate
也支持独立于 transform
属性,单独声明平移变换。
translate: 50% 105px 5rem;
倾斜(skew)
使用
skew()
函数可以将元素在水平方向和垂直方向上倾斜指定的角度。当只有一个参数时,表示水平方向的倾斜角度;当有两个参数时,第一个参数表示水平方向的倾斜角度,第二个参数表示垂直方向的倾斜角度。
// 将元素在水平方向上倾斜30度
transform: skew(30deg);
矩阵变换(matrix)
CSS的
matrix
属性是用于实现2D变换效果的函数,它基于数学中的矩阵概念。通过矩阵的乘法运算,可以将多个变换效果组合在一起,实现复杂的变换效果。
语法
matrix(a, b, c, d, tx, ty);
matrix( scaleX(), skewY(), skewX(), scaleY(), translateX(), translateY() )
其中,a
和d
控制元素在水平方向和垂直方向上的缩放,b
和c
控制元素在水平和垂直方向上的倾斜,tx
和ty
控制元素在水平和垂直方向上的平移。
矩阵的六个参数对应于一个2x3的矩阵。这六个参数给定特定的值,可以实现特殊的变换效果。
实现平移效果,修改参数
tx
和ty
;实现缩放效果,修改参数
a
和d
;实现旋转效果,修改参数
a
,b
,c
, 和d
。
例如,要实现一个元素的平移效果,可以将矩阵设置为:
transform: matrix(1, 0, 0, 1, 100px, 50px);
这个例子将元素在X轴方向上平移100像素,在Y轴方向上平移50像素。
需要注意的是,CSS中的矩阵变换是基于2D变换的,不包含3D变换效果。对于更复杂的3D变换效果,可能需要使用其他的转换函数,如rotateX、rotateY、rotateZ等。
实例
旋转+缩放动画
多种组合变换
在这个示例中:
translate(x, y)
用于在X轴和Y轴上移动对象。rotate(angle)
用于按指定角度旋转对象。scale(x, y)
用于在X轴和Y轴上缩放对象。skew(x-angle, y-angle)
用于在X轴和Y轴上倾斜对象。matrix(a, b, c, d, e, f)
是一个综合性的函数,允许组合多个变换。
可访问代码地址查看源码实现
过渡(Transition)
CSS 过渡可以决定哪些属性发生动画效果(通过明确地列出这些属性),何时开始(通过设置延时),持续多久(通过设置时长)以及如何动画(通过定义缓动函数,比如线性或先快后慢)。
基本语法
transition: property | duration | timing-function | delay;
transition属性是一个简写属性,用于设置四个过渡相关的子属性:
- property:指定应用过渡效果的CSS属性名称,例如width、height、background-color等。可以使用all来指定所有可动画的属性都将应用过渡效果。
- duration:定义过渡效果的持续时间,通常以秒(s)或毫秒(ms)为单位。例如,2s或2000ms表示过渡效果将在2秒内完成。
- timing-function:定义过渡效果的速度曲线。常见的值包括linear(匀速)、ease(慢到快再到慢)、ease-in(慢到快)、ease-out(快到慢)
- ease-in-out(慢到快再到慢)等,或者可以使用cubic-bezier()函数来自定义速度曲线。
- delay:定义过渡效果开始前的延迟时间,也以秒或毫秒为单位。例如,1s或1000ms表示过渡效果将在1秒后开始。
这些子属性也可以单独设置:
transition-property: width;
transition-duration: 2s;
transition-timing-function: ease-in-out;
transition-delay: 1s;
实例
鼠标悬浮,修改卡片的缩放、背景颜色和阴影
可访问代码地址查看源码实现
三、CSS动画性能及优化
性能瓶颈
CSS原生动画的性能瓶颈主要来自于两个方面:计算复杂度和渲染性能。
计算复杂度
计算复杂度指浏览器在处理动画效果时所需的计算量。这主要涉及到样式的计算、布局(Layout)和绘制(Paint)操作。如果动画涉及复杂的样式计算或引发频繁的布局和绘制,可能会导致性能瓶颈。以下是一些具体的例子:
// 复杂样式计算
.element { width: calc(50% + 100px); height: calc(30vh - 20px); background-color: hsl(120, 70%, 80%);
}// 在动画中频繁获取布局属性
const elementWidth = element.offsetWidth;// 复杂的选择器可能需要更多的计算资源来匹配元素
.container > div:not(:last-child):hover {transform: scale(1.2);
}
渲染性能
渲染性能涉及浏览器如何绘制动画帧以及如何在屏幕上显示它们。这包括合成图层的创建、纹理的合成和屏幕的刷新。过于复杂或频繁的渲染操作可能导致动画不流畅,尤其是在性能较低的设备上。
// 鼠标悬停时会导致频繁的重绘和回流
.element {left: 10px;top: 10px;transition: left 1s, top 1s;
}.element:hover {left: 100px;top: 100px;
}// 在某些情况下,为多个元素应用硬件加速可能会导致更多的复合层,增加渲染工作量。
.element1, .element2, .element3 {transform: translateZ(0);
}// 过于频繁的透明度变化可能导致浏览器强制进行重绘
.element {transition: opacity 0.5s;
}
.element:hover {opacity: 0.5;
}
此外,还有一些其他因素也会影响CSS原生动画的性能,例如浏览器对CSS动画的支持程度、硬件性能等。例如,一些老旧的浏览器可能不支持某些CSS动画特性,或者在某些设备上,GPU性能不足也会影响动画的性能。
优化方法
使用硬件加速
通过开启硬件加速,将计算密集型的任务交给GPU处理,可以大大提高动画的性能。
在CSS中,可以使用transform
属性或opacity
等属性来开启硬件加速。
在个别复杂的计算场景下,也可以使用will-change
属性。该属性提供了一种告知浏览器该元素会有哪些变化的方法,这样浏览器可以在元素属性真正发生变化之前提前做好对应的优化准备工作。具体需要结合业务场景综合考量并使用。
使用requestAnimationFrame
requestAnimationFrame是一个高性能的API,它可以根据屏幕的刷新率来同步动画的帧率,从而保证动画的流畅度。应尽量使用requestAnimationFrame来控制动画的播放和暂停。
减少重绘和重排
重绘和重排是导致动画卡顿的主要原因之一。可以通过减少不必要的样式计算和布局更新来减少重排和重绘。例如,避免在动画过程中频繁改变元素的布局或大小,尽可能使用transform属性代替top、left等属性,因为transform属性的改变不会触发重排。
避免使用过多的box-shadow和gradients
box-shadow和gradients会消耗大量的GPU资源,特别是在移动设备上。如果可以,尽量避免在动画元素上使用它们,或者尽量减少它们的数量和复杂性。
合理使用CSS选择器
复杂的CSS选择器会导致浏览器进行大量的样式计算,从而影响动画性能。应尽量避免使用过于复杂的选择器,或者尽量减少它们的数量和使用频率。
优化关键帧动画
对于关键帧动画,可以通过合理地拆分和组织关键帧来减少动画的复杂度,从而提高性能。例如,将多个动画拆分成多个独立的动画,或者将一些不重要的动画移到非关键帧中。
四、CSS动画库
随着前端开发的发展,出现了一系列独立的CSS动画库,这些库旨在提供更丰富的特性、更简洁的API、更好的性能和更好的开发体验。
- Animate.css:一款开箱即用的跨浏览器动画库,适用于web项目。非常适合与效果增强、主页、滑块和操作引导提示。
- Magic Animation:一组简单的动画,可包含在web或app项目中,提供具有特殊效果的CSS3动画。
- Animista: 一个在线CSS动画生成器,可以在网站上选择预定义的动画类型和参数,然后生成相应的CSS代码。
- Cssanimation.io: 一个在线CSS动画代码生成器,可以选择不同的动画效果,如淡入淡出、滑动等,并设置动画的持续时间和延迟时间。
- Vivify:一个CSS动画库,提供了许多实用的动画效果类,可以方便地应用于网页元素上。它扩展了Animate CSS,不仅提供了类似的动画效果,还增加了一些额外的类和功能。使用Vivify,可以通过简单的类名来控制动画的持续时间和延迟时间等参数。
五、使用场景
原生CSS动画和CSS动画库各有适用场景,选择哪种主要取决于项目的具体需求。
原生CSS动画使用场景
- 简单的动画效果: 对于一些基本的、简单的动画效果,如淡入淡出、位移等,原生CSS动画足够满足需求。
- 性能优势: 原生CSS动画通常能够充分利用浏览器的硬件加速,性能较好。对于轻量级的动画,避免引入额外的库可以提高性能。
- 低维护成本: 对于小型项目或者仅有一些简单动画的项目,使用原生CSS动画可以减少依赖,降低维护成本。
- 响应式设计: 对于一些基于媒体查询实现的响应式动画,原生CSS动画更容易集成到响应式设计中。
CSS动画库使用场景
- 丰富的动画效果: CSS动画库通常提供了大量的动画效果,尤其是一些复杂的、专业设计的效果,可以方便地应用于项目。
- 快速开发: 在快速开发周期内,使用动画库可以减少编写和调试动画代码的时间,提高开发效率。
- 跨浏览器兼容性: 动画库通常经过测试和优化,能够解决不同浏览器之间的兼容性问题,减少开发者的兼容性工作。
- 复杂场景和交互性: 当项目需要复杂的交互动画、复合动画或需要在多个元素之间同步动画时,使用动画库更为方便。
- 动画的控制: 一些动画库提供了更高级的控制机制,例如暂停、恢复、反向播放等功能,使得动画更易于管理。