CSS3 不執行 Transition 過渡動畫
阿新 • • 發佈:2018-12-21
如果元素設定了transition,那麼當 JavaScript 改變相應屬性值的時候,就會觸發該過渡動畫。
有時候,我們想直接設定該值,而不觸發過渡動畫,最直觀的想法就是先設定 transition-duration 為0,然後設定該值,最後恢復 transition 的值。但是這個方法是行不通的,因為JavaScript是單執行緒的,它採用訊息機制,當我們給元素賦予某個樣式的時候,它並沒有立即執行,而是繼續處理當前的訊息佇列,直到進入到某個專門處理CSS的階段(RecalculateStyle)。**這點和Node.js的事件機制很像。**前面說到JavaScript是單執行緒,因此採用上面方法的結果是“對同一個屬性賦值,後面的覆蓋前面的”,因此後續觸發RecalculateStyle的時候,依然會觸發過渡動畫。
因此,解決該問題的思路就有兩種
- 修改訊息的先後順序。
通過人為的設定一個延遲(setTimeout、requestAnimationFrame),使transition的設定在RecalculateStyle之後被處理 - 手動觸發 RecalculateStyle 使得修改生效。
注意到有個 getComputedStyle 方法用來獲取計算後的樣式(以前我常用在獲取偽元素的樣式上),既然要計算樣式,那麼必定會觸發 RecalculateStyle,這樣之前的CSS就被處理了。
測試程式碼如下:
<!DOCTYPE html> <html> <head> <meta charset="utf8"> <style> body { display: flex; } div { width: 15em; height: 10em; border: 1px solid black; margin: 1em; display: flex; justify-content: center; align-items: center; } </style> <script> //js中是沒有node.js的process.nextTick和window.setImmediate這兩個方法的 window.onload = ()=> { const [div1, div2, div3, div4, div5] = document.getElementsByTagName("div"); div1.style.backgroundColor = "red"; div1.style.transition = "background-color 5s"; div2.style.backgroundColor = "red"; window.setTimeout(()=>{ div2.style.transition = "background-color 5s"; }, 100); div3.style.backgroundColor = "red"; const start = new Date().getTime(); window.requestAnimationFrame(()=>{ const end = new Date().getTime(); const cost = end-start; console.log(cost); //我這裡是只花了18ms div3.style.transition = "background-color 5s"; }); div4.style.color = "yellow"; div4.style.backgroundColor = "red"; div4.style.marginLeft = "4em"; //獲取的並不一定要是transition中設定的屬性,通常隨便獲取一個屬性都會導致RecalculateStyle(animation、transition等少部分屬性不在其中) getComputedStyle(div4).length; //這段一定要放在獲取只讀的計算屬性之後 div4.style.transition = "all 5s"; } </script> </head> <body> <div>原始</div><div>setTimeout</div><div>requestAnimationFrame</div><div>getComputedStyle</div> </body> </html>