动画:24帧
游戏:30帧
现在大部分显示器的最低刷新频率为60Hz,即每秒60帧。
setInterval()制作动画
setInterval()可被用于实现css动画,使用position: relative
并改变其属性(比如left)。
e.g.
html
css
#demo {
width: 100px;
height: 100px;
border: 1px solid red;
position: relative;
left:0;
}
js
var n=1;
var id = setInterval(() => {
if (n<=200){
demo.style.left=n+'px';
n=n+1;
}
else{
clearInterval(id);
}
}, 1000/60);
tips:关于停止setInterval()
setInterval()在窗口和工作接口上提供的setInterval()方法重复调用函数或执行代码片段,每次调用之间有固定的时间延迟。它返回一个时间间隔ID,该ID唯一地标识时间间隔,因此您可以稍后通过调用clearInterval()来删除它。
因此可利用clearInterval()清除唯一的ID停止setInterval()
var id = setInterval(() => {
if (condition){
statements ...
}
else{
clearInterval(id)
}
}, 1000/60)
tips:paint flashing观察性能
develop tool中打开rendering 勾上Paint flashing,能观察到CSS是否重新渲染
transform做动画
html
css
#demo {
width: 100px;
height: 100px;
border: 1px solid red;
transition: all is linear;
}
/* 设置transform动画 */
#demo.end {
transform: translateX(200px);
}
js
setTimeout(()=>{
demo.classList.add('end');
}, 3000);
transform制作的动画图形并非缓慢移动,而是急速闪现在目标位置。
transform触发的css渲染次数远远少于setInterval()
浏览器渲染原理
- 构建 DOM - HTML tree
- 构建 CSSOM - CSS tree
- 合并 DOM, CSSOM -> Render tree
- 根据渲染树构成 Layout (文档流,盒模型,计算大小、位置),形成线框。
- Paint, 绘制边框颜色,文字颜色,阴影等。
- Compose 根据层叠关系合成,展示画面。
执行js脚本 -> 构建style -> 形成layout -> 绘制页面 -> 合成最终画面
渲染的三种更新方式中,layout和paint可能会被省略。根据颜色和位置大小的改编决定哪种会被省略。
- 完全更新:对布局位置的修改会触发(div.remove()),元素relayout
- 跳过layout更新:修改背景颜色会触发,repaint + composite
- 跳过layout + paint更新:元素位移(transform)会触发,composite。需要全屏查看,iframe有问题。
tips: 查看元素渲染
csstrigger.com 提供了所有css元素在不同浏览器上的渲染过程。
CSS优化
- 渲染性能:Google开发者文档https://developers.google.com/web/fundamentals/performance/rendering
- JS优化:使用 requestAnimationFrame()替代 setTimeout() 或者 setInterval()
- CSS优化:使用 will-change 或者 translate属性
transform 用法
MDN文档有语法格式 https://developer.mozilla.org/zh-CN/docs/Web/CSS/transform
transform属性均可组合使用。比如放大的同时位移。
translate 位移
X: 横轴
Y: 纵轴
Z: 从显示器到屏幕的距离。通过perspective属性设置视点。
transform: translate3d(x, y, z)
transform: translateX(x_value) translateY(y_value)
transform: translate(x_value, y_value)
/* 绝对居中的一种写法(IE不支持) */
top: 50%;
left: 50%;
transform: translate(-50%, -50%)
scale 缩放
倍数缩放
-
transform: scale(1.5)
整体放大1.5倍 -
scaleX(x_value), scaleY(y_value), scaleZ(z_value)
X, Y, Z 按比缩放 -
scale3d(x_value, y_value, z_value)
X, Y, Z三轴各自按比缩放 -
transform: scale(x_value, y_value)
X轴,Y轴各自缩放 -
transform: scale(x_value, y_value, z_value)
相当于于scale3d函数,X, Y, Z三轴各自按比缩放
rotate 旋转
transform: rotate( deg | turn | rad )
transform: = rotate3d(x_value, y_value, z_value)
transform: rotateX( x_value )
transform: rotateY( y_value )
transform: rotateZ( z_value )
skew 倾斜
-
transform: skew(deg)
用法基本同上,xyz三轴均可。
transition 过渡
添加中间帧
transition: 属性 时长 过渡方式 延迟
- all可以代表所有属性
- 过渡方式: linear, ease, ease-in, ease-out, ease-in-out, cubic-bezier, step-start, step-end, steps
- background颜色可以过渡
- opacity透明度可以过渡
不适用的情况: - display: block => display: none 不显示则无结果。虽然看不见但位置还在。如果想要消失效果,使用visibility: visible => visibility: hidden
animation
标准写法:
animation: 时长 | 过渡方式 | 延迟 | 次数 | 方向 | 填充模式 | 是否暂停 | 动画名
- 百分数
#example{
animation: time forwards identifier;
}
@keyframes identifier {
0% { attributes;}
66% { attributes;}
100% { attributes;}
}
- from to
#example{
animation: time forwards identifier;
}
@keyframes identifier {
from { attributes;}
66% { attributes;}
to { attributes;}
}
forwards: 属于填充模式 让动画停在最后一帧。
回流 (Reflow)
当Render Tree中部分或全部元素的尺寸、结构、或某些属性发生改变时,浏览器重新渲染部分或全部文档的过程称为回流。
会导致回流的操作:
- 页面首次渲染
- 浏览器窗口大小发生改变
- 元素尺寸或位置发生改变
-元素内容变化(文字数量或图片大小等等) - 元素字体大小变化
- 添加或者删除可见的DOM元素
- 激活CSS伪类(例如::hover)
- 查询某些属性或调用某些方法
一些常用且会导致回流的属性和方法:
clientWidth、clientHeight、clientTop、clientLeft
offsetWidth、offsetHeight、offsetTop、offsetLeft
scrollWidth、scrollHeight、scrollTop、scrollLeft
scrollIntoView()、scrollIntoViewIfNeeded()
getComputedStyle()
getBoundingClientRect()
scrollTo()
重绘 (Repaint)
当页面中元素样式的改变并不影响它在文档流中的位置时(例如:color、background-color、visibility等),浏览器会将新样式赋予给元素并重新绘制它,这个过程称为重绘。
性能影响
回流(reflow)比重绘(repaint)的代价要更高。
有时即使仅仅回流一个单一的元素,它的父元素以及任何跟随它的元素也会产生回流。
现代浏览器会对频繁的回流或重绘操作进行优化:
浏览器会维护一个队列,把所有引起回流和重绘的操作放入队列中,如果队列中的任务数量或者时间间隔达到一个阈值的,浏览器就会将队列清空,进行一次批处理,这样可以把多次回流和重绘变成一次。
当你访问以下属性或方法时,浏览器会立刻清空队列:
clientWidth、clientHeight、clientTop、clientLeft
offsetWidth、offsetHeight、offsetTop、offsetLeft
scrollWidth、scrollHeight、scrollTop、scrollLeft
width、height
getComputedStyle()
getBoundingClientRect()
因为队列中可能会有影响到这些属性或方法返回值的操作,即使你希望获取的信息与队列中操作引发的改变无关,浏览器也会强行清空队列,确保你拿到的值是最精确的。
Reflow & Repaint 部分 引用自:https://juejin.cn/post/6844903569087266823
一颗小红心:
- transform, transition and hover
http://js.jirengu.com/hogucoluqo/1/edit?html,css,output - animation
http://js.jirengu.com/mepakaraco/1/edit?html,css,output