1.【CSS 动画基础】
动画原理
-
- 许多静止的画面(帧)以一定的速度(30 帧 / s)连续播放时,眼睛因视觉残像产生错觉,而误以为是活动的画面。
动画的渲染性能
-
- 在开发者工具中打开 Rendering 面板,勾选 'Paint falshing' 选项,页面上重新绘制(repaint)的地方会变绿;必须全屏查看效果,在 iframe 里看会有问题
- 使用 setInterval 实现的动画在执行过程中会不停地重新渲染,性能较差
- 使用 transform 实现的动画在执行过程中重新渲染的次数很少,性能提升很多
浏览器渲染原理
-
- 根据 HTML 构建 HTML 树(DOM)
- 根据 CSS 构建 CSS 树(CSSOM),和 DOM 不完全一样
- 将两棵树合并成一颗渲染树(Render Tree),就是用户最终看到的树
- 进行布局(Layout),将元素定位,设置大小(文档流、盒模型)
- 进行绘制(Paint),将边框颜色、文字颜色、阴影等画出来
- 进行合成(Compose),根据层叠关系展示画面
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5iM5MGZwYzYyU2YiNGN2EWYwQGZwQ2N0YmYxATZjNTN38CX0JXZ252bj91Ztl2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
更新样式的方法
-
- 一般使用 JS 来更新样式
- div.style.background = 'red' 设置背景色
- div.style.display = 'none' 隐藏元素
- div.classList.add('red') 添加类,最常用,一个类可以包含很多样式
- div.remove() 删除节点
三种不同的渲染方式
-
- 方式1:布局 > 绘制 > 合成,div.remove(),会触发当前元素消失,其他元素 relayout
- 方式2:绘制 > 合成,例如改变背景色
- 方式3:只需合成,性能最好,例如 transform
- 如何知道每个 CSS 属性使用哪种渲染方式:https://csstriggers.com/
- Chrome 浏览器内核 = Blink
- Firefox 浏览器内核 = Gecko
- Safari 浏览器内核 = Webkit
- edge 浏览器内核 = EdgeHTML
CSS 动画优化
-
- 使用 transform 代替 left
- 使用 will-change 或 translate 属性
- 优化 JS:使用 requestAnimationFrame 代替 setTimeout 和 setInterval
- 绘制通常是性能开销最大的部分,应尽可能避免绘制;除 transform 和 opacity 属性之外,更改任何属性始终都会触发绘制。
2.【transform 变形】
四种常用变形
-
- 位移 translate
- translateX( <length-percentage> ) 横向位移
- translateY( <length-percentage> ) 纵向位移
- translateZ( <length> ) Z轴位移,在 3D 视图中才会生效,需要在父元素添加属性 perspective,设置透视图的视点位置
- translate( x, y ) 二维位移的简写形式
- translate3d( x, y, z ) 三维位移的简写形式
- 参数可以是百分数,使用 translate(-50%, -50%) 配合 left:50%; top:50% 可以设置绝对定位元素的居中
- 缩放 scale
- scale( <number>, <number>? ) 设置元素缩放比例,1 为原比例
- 也可使用 scaleX | scaleY 分别设置横/纵向的缩放比例
- 使用 scale 缩放会导致 border 也变宽/窄,容易出现模糊,因此很少使用
- 旋转 rotate
- rotate( [<angle> | <zero>] ) 从12点钟方向顺时针旋转,角度单位 360deg
- 默认围绕 Z 轴转动,也可以围绕 X 轴或 Y 轴 转动,rotateX | rotateY
- 一般用于制作 360° 旋转的 loading 图标
- 倾斜 skew
- skewX( [<angle> | <zero>] ) 沿 X 轴倾斜,用的较少
- 位移 translate
经验技巧
- 动画调试技巧:在开发者工具中选中 transform 属性后的数值,按 ↑ ↓ 可以实时增减数值,按住 shift 可以加大增减幅度
- 可以添加多个效果,用空格隔开
- transform: none; 清除所有效果
- 一般与 transition(过渡)配合使用,产生动画效果 transition: all 1s
- inline 元素不支持 transform 属性,需要先转换为 block 元素
3.【transition 过渡】
- 作用是补充中间帧,形成动画效果
- transition 属性名 时长 过渡方式 延迟
- 举例:transition: left 200ms linear 3s
- 过渡方式:linear 线性,匀速变化 | ease 先快后慢,默认 | ease-in 淡入 | ease-out 淡出 | ease-in-out 淡入+淡出 | 等等
- 可以用逗号分隔两个不同属性:transition: left 200ms, top 400ms
- 可以用 all 代表所有属性:transition: all 200ms
- 并不是所有属性都能过渡
- display: none <==> block 不能过渡
- 可以使用 visibility: hidden <==> visible 切换元素是否可见
- opacity: 0 只能让元素看不见,但是位置和大小还在那里,一般需要在动画执行后删除元素 div.addEventListener('transitionend', ()=> { div.remove() })
- background 也可以过渡,因为是16进制的颜色值
- 多次过渡动画
- .a ==> .b .b ==> .c ,使用 div.classList.remove 和 classList.add 改变元素的css类,注意第二次变形要保留第一次变形的状态
4. 【animation 动画】
- animation: 时长 | 过渡方式 | 延迟 | 次数 | 方向 | 填充模式 | 是否暂停 | 关键帧名
- 过渡方式:和 transition 取值一样,默认 ease
- 次数:3 | 2.4 | infinite(无限)
- 方向:reverse(反向) | alternate(交替) | alternate-reverse
- 填充模式:none | forwards(停在最后一帧) | backwards | both
- 是否暂停:paused | running 可以通过 div.style.animationPlayState = 'paused | running' 控制动画暂停、恢复
- 每个属性都有单独的属性名
- @keyframes 关键帧的两种语法
@