動(dòng)畫:24幀
游戲:30幀
現(xiàn)在大部分顯示器的最低刷新頻率為60Hz,即每秒60幀。
setInterval()制作動(dòng)畫
setInterval()可被用于實(shí)現(xiàn)css動(dòng)畫,使用position: relative并改變其屬性(比如left)。
e.g.
html
<div id="demo"></div>
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:關(guān)于停止setInterval()
setInterval()在窗口和工作接口上提供的setInterval()方法重復(fù)調(diào)用函數(shù)或執(zhí)行代碼片段,每次調(diào)用之間有固定的時(shí)間延遲。它返回一個(gè)時(shí)間間隔ID,該ID唯一地標(biāo)識(shí)時(shí)間間隔,因此您可以稍后通過調(diào)用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做動(dòng)畫
html
<div id="demo"></div>
css
#demo {
width: 100px;
height: 100px;
border: 1px solid red;
transition: all is linear;
}
/* 設(shè)置transform動(dòng)畫 */
#demo.end {
transform: translateX(200px);
}
js
setTimeout(()=>{
demo.classList.add('end');
}, 3000);
transform制作的動(dòng)畫圖形并非緩慢移動(dòng),而是急速閃現(xiàn)在目標(biāo)位置。
transform觸發(fā)的css渲染次數(shù)遠(yuǎn)遠(yuǎn)少于setInterval()
瀏覽器渲染原理
- 構(gòu)建 DOM - HTML tree
- 構(gòu)建 CSSOM - CSS tree
- 合并 DOM, CSSOM -> Render tree
- 根據(jù)渲染樹構(gòu)成 Layout (文檔流,盒模型,計(jì)算大小、位置),形成線框。
- Paint, 繪制邊框顏色,文字顏色,陰影等。
- Compose 根據(jù)層疊關(guān)系合成,展示畫面。
執(zhí)行js腳本 -> 構(gòu)建style -> 形成layout -> 繪制頁面 -> 合成最終畫面
渲染的三種更新方式中,layout和paint可能會(huì)被省略。根據(jù)顏色和位置大小的改編決定哪種會(huì)被省略。
- 完全更新:對(duì)布局位置的修改會(huì)觸發(fā)(div.remove()),元素relayout
- 跳過layout更新:修改背景顏色會(huì)觸發(fā),repaint + composite
- 跳過layout + paint更新:元素位移(transform)會(huì)觸發(fā),composite。需要全屏查看,iframe有問題。
tips: 查看元素渲染
csstrigger.com 提供了所有css元素在不同瀏覽器上的渲染過程。
CSS優(yōu)化
- 渲染性能:Google開發(fā)者文檔https://developers.google.com/web/fundamentals/performance/rendering
- JS優(yōu)化:使用 requestAnimationFrame()替代 setTimeout() 或者 setInterval()
- CSS優(yōu)化:使用 will-change 或者 translate屬性
transform 用法
MDN文檔有語法格式 https://developer.mozilla.org/zh-CN/docs/Web/CSS/transform
transform屬性均可組合使用。比如放大的同時(shí)位移。
translate 位移
X: 橫軸
Y: 縱軸
Z: 從顯示器到屏幕的距離。通過perspective屬性設(shè)置視點(diǎn)。
transform: translate3d(x, y, z)
transform: translateX(x_value) translateY(y_value)
transform: translate(x_value, y_value)
/* 絕對(duì)居中的一種寫法(IE不支持) */
top: 50%;
left: 50%;
transform: translate(-50%, -50%)
scale 縮放
倍數(shù)縮放
-
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)相當(dāng)于于scale3d函數(shù),X, Y, Z三軸各自按比縮放
rotate 旋轉(zhuǎn)
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: 屬性 時(shí)長(zhǎng) 過渡方式 延遲
- all可以代表所有屬性
- 過渡方式: linear, ease, ease-in, ease-out, ease-in-out, cubic-bezier, step-start, step-end, steps
- background顏色可以過渡
- opacity透明度可以過渡
不適用的情況: - display: block => display: none 不顯示則無結(jié)果。雖然看不見但位置還在。如果想要消失效果,使用visibility: visible => visibility: hidden
animation
標(biāo)準(zhǔn)寫法:
animation: 時(shí)長(zhǎng) | 過渡方式 | 延遲 | 次數(shù) | 方向 | 填充模式 | 是否暫停 | 動(dòng)畫名
- 百分?jǐn)?shù)
#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: 屬于填充模式 讓動(dòng)畫停在最后一幀。
回流 (Reflow)
當(dāng)Render Tree中部分或全部元素的尺寸、結(jié)構(gòu)、或某些屬性發(fā)生改變時(shí),瀏覽器重新渲染部分或全部文檔的過程稱為回流。
會(huì)導(dǎo)致回流的操作:
- 頁面首次渲染
- 瀏覽器窗口大小發(fā)生改變
- 元素尺寸或位置發(fā)生改變
-元素內(nèi)容變化(文字?jǐn)?shù)量或圖片大小等等) - 元素字體大小變化
- 添加或者刪除可見的DOM元素
- 激活CSS偽類(例如::hover)
- 查詢某些屬性或調(diào)用某些方法
一些常用且會(huì)導(dǎo)致回流的屬性和方法:
clientWidth、clientHeight、clientTop、clientLeft
offsetWidth、offsetHeight、offsetTop、offsetLeft
scrollWidth、scrollHeight、scrollTop、scrollLeft
scrollIntoView()、scrollIntoViewIfNeeded()
getComputedStyle()
getBoundingClientRect()
scrollTo()
重繪 (Repaint)
當(dāng)頁面中元素樣式的改變并不影響它在文檔流中的位置時(shí)(例如:color、background-color、visibility等),瀏覽器會(huì)將新樣式賦予給元素并重新繪制它,這個(gè)過程稱為重繪。
性能影響
回流(reflow)比重繪(repaint)的代價(jià)要更高。
有時(shí)即使僅僅回流一個(gè)單一的元素,它的父元素以及任何跟隨它的元素也會(huì)產(chǎn)生回流。
現(xiàn)代瀏覽器會(huì)對(duì)頻繁的回流或重繪操作進(jìn)行優(yōu)化:
瀏覽器會(huì)維護(hù)一個(gè)隊(duì)列,把所有引起回流和重繪的操作放入隊(duì)列中,如果隊(duì)列中的任務(wù)數(shù)量或者時(shí)間間隔達(dá)到一個(gè)閾值的,瀏覽器就會(huì)將隊(duì)列清空,進(jìn)行一次批處理,這樣可以把多次回流和重繪變成一次。
當(dāng)你訪問以下屬性或方法時(shí),瀏覽器會(huì)立刻清空隊(duì)列:
clientWidth、clientHeight、clientTop、clientLeft
offsetWidth、offsetHeight、offsetTop、offsetLeft
scrollWidth、scrollHeight、scrollTop、scrollLeft
width、height
getComputedStyle()
getBoundingClientRect()
因?yàn)殛?duì)列中可能會(huì)有影響到這些屬性或方法返回值的操作,即使你希望獲取的信息與隊(duì)列中操作引發(fā)的改變無關(guān),瀏覽器也會(huì)強(qiáng)行清空隊(duì)列,確保你拿到的值是最精確的。
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