1.【CSS 動畫基礎】
動畫原理
-
- 許多靜止的畫面(幀)以一定的速度(30 幀 / s)連續播放時,眼睛因視覺殘像産生錯覺,而誤以為是活動的畫面。
動畫的渲染性能
-
- 在開發者工具中打開 Rendering 面闆,勾選 'Paint falshing' 選項,頁面上重新繪制(repaint)的地方會變綠;必須全屏檢視效果,在 iframe 裡看會有問題
- 使用 setInterval 實作的動畫在執行過程中會不停地重新渲染,性能較差
- 使用 transform 實作的動畫在執行過程中重新渲染的次數很少,性能提升很多
浏覽器渲染原理
-
- 根據 HTML 建構 HTML 樹(DOM)
- 根據 CSS 建構 CSS 樹(CSSOM),和 DOM 不完全一樣
- 将兩棵樹合并成一顆渲染樹(Render Tree),就是使用者最終看到的樹
- 進行布局(Layout),将元素定位,設定大小(文檔流、盒模型)
- 進行繪制(Paint),将邊框顔色、文字顔色、陰影等畫出來
- 進行合成(Compose),根據層疊關系展示畫面
更新樣式的方法
-
- 一般使用 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 關鍵幀的兩種文法
@