關鍵要點
transform
和opacity
等屬性,避免增加之前步驟的負擔。 left
、top
、right
、bottom
屬性進行動畫過渡,它們會導致不流暢的動畫;應使用影響合成步驟的transform
屬性,讓瀏覽器在動畫開始前確定圖層穩定性。 will-change
屬性將元素提升到另一個圖層,避免瀏覽器處理佈局渲染或繪製。 本文最初發表於OutSystems。感謝支持SitePoint的合作夥伴。
在移動應用中製作動畫很容易。如果遵循以下技巧,在移動應用中正確地製作動畫也很容易……儘管如今每個人都在移動設備上使用CSS3動畫,但許多人使用方式不正確。開發人員經常忽略最佳實踐。這是因為人們不理解這些實踐存在的原因以及為什麼它們受到如此強烈的支持。設備規格範圍很廣。因此,如果不優化代碼,就會為大部分用戶提供低於標準的體驗。記住:一些高端旗艦設備功能強大,但世界上大多數人使用的設備與這些高性能設備相比,就像帶有LCD屏幕的算盤。我們希望幫助您正確地利用CSS3的強大功能。為此,我們需要先了解一些事情。
理解時間線
瀏覽器在渲染和處理元素時會做什麼?這個時間線稱為關鍵渲染路徑:
圖片來源:www.csstriggers.com
為了實現流暢的動畫,我們需要專注於更改影響合成步驟的屬性,而不是增加之前步驟的負擔。
樣式 瀏覽器開始計算要應用於元素的樣式——重新計算樣式。
佈局 在接下來的步驟中,瀏覽器生成每個元素的形狀和位置——佈局。在這裡,瀏覽器設置頁面屬性,例如寬度和高度,以及例如其邊距或
left
、top
、right
、bottom
。
繪製 瀏覽器將每個元素的像素填充到圖層中。它參考這些屬性:
box-shadow
、border-radius
、color
、background-color
等。
合成 這是您想要執行動畫的地方,因為這是瀏覽器將所有圖層繪製到屏幕上的時候。 現代瀏覽器可以很好地動畫化四個樣式屬性,利用
transform
和opacity
屬性。
transform: translateX(n) translateY(n) translateZ(n);
transform: scale(n);
transform: rotate(ndeg);
opacity: n;
如何達到每秒60幀
記住這一點,現在是擼起袖子加油幹的時候了。讓我們從HTML開始。我們將創建一個非常簡單的結構並將我們的app-menu
放在一個layout
類中。
<code class="language-html"><div> <div></div> <div> <div></div> </div> </div></code>
錯誤的方法
<code class="language-css">.app-menu { left: -300px; transition: left 300ms linear; } .app-menu-open .app-menu { left: 0px; transition: left 300ms linear; }</code>
看到我們更改的屬性了嗎?應避免使用left
、top
、right
、bottom
屬性進行過渡。這些不會創建流暢的動畫,因為它們每次都會強制瀏覽器執行佈局傳遞,這會影響所有元素的子元素。結果是這樣的:
該動畫不夠流暢。我們使用DevTools時間線檢查幕後發生了什麼,結果如下:
綠色區域表示渲染動畫所花費的時間。此數據顯示幀率不規則且性能緩慢。 “綠色條表示FPS。高條表示動畫以60 FPS渲染。低條表示低於60 FPS。因此,理想情況下,您希望綠色條在整個時間線上始終保持較高。紅色條也表示卡頓,因此,另一種衡量進度的方法是消除這些紅色條。”感謝Kayce Basques!
使用Transform
<code class="language-css">.app-menu { -webkit-transform: translateX(-100%); transform: translateX(-100%); transition: transform 300ms linear; } .app-menu-open .app-menu { -webkit-transform: none; transform: none; transition: transform 300ms linear; }</code>
transform
屬性影響合成步驟,而不是佈局。在這裡,我們告知瀏覽器我們的圖層在動畫開始前是穩定的,因此在渲染動畫時遇到的障礙更少。
時間線正是這樣反映的:
結果開始變得更好,幀率似乎已經穩定,因此動畫運行更流暢。
在GPU中運行動畫
然後,讓我們更上一層樓。為了真正使其運行流暢,我們將使用GPU渲染動畫。
<code class="language-html"><div> <div></div> <div> <div></div> </div> </div></code>
儘管一些瀏覽器仍然需要translateZ()
或translate3d()
作為後備,但will-change
屬性是未來。此屬性將元素提升到另一個圖層,因此瀏覽器不必考慮佈局渲染或繪製。
看到它有多流暢了嗎?時間線證實了這一點:
動畫的幀率更恆定,動畫渲染速度更快。但在開頭仍然有一個很長的幀運行:開頭有點瓶頸。還記得我們一開始創建的HTML結構嗎?讓我們看看我們如何在JavaScript中控制app-menu
div:
<code class="language-css">.app-menu { left: -300px; transition: left 300ms linear; } .app-menu-open .app-menu { left: 0px; transition: left 300ms linear; }</code>
啊哈!我們在這里通過向layout
div添加類導致了一個問題。這迫使瀏覽器重新生成我們的樣式樹——這影響了渲染性能。
每秒60幀的黃油般順滑的解決方案
如果我們將菜單創建在視口區域之外呢?將菜單放在隔離區域將確保我們只影響我們希望動畫化的元素。因此,我們建議使用以下HTML結構:
<code class="language-css">.app-menu { -webkit-transform: translateX(-100%); transform: translateX(-100%); transition: transform 300ms linear; } .app-menu-open .app-menu { -webkit-transform: none; transform: none; transition: transform 300ms linear; }</code>
現在我們必須以稍微不同的方式控制菜單的狀態。我們將使用JavaScript中的transitionend
函數來操作在動畫結束時刪除的類中的動畫。
<code class="language-css">.app-menu { -webkit-transform: translateX(-100%); transform: translateX(-100%); transition: transform 300ms linear; will-change: transform; }</code>
讓我們將所有內容放在一起並檢查結果。這是一個完整的啟用CSS3的示例,所有內容都放在正確的位置:
<code class="language-javascript">function toggleClassMenu() { var layout = document.querySelector(".layout"); if(!layout.classList.contains("app-menu-open")) { layout.classList.add("app-menu-open"); } else { layout.classList.remove("app-menu-open"); } } var oppMenu = document.querySelector(".menu-icon"); oppMenu.addEventListener("click", toggleClassMenu, false);</code>
時間線向我們展示了什麼?
全是綠色的條,寶貝。想看一個實際例子嗎?點擊這裡。 (此處應插入實際鏈接)
(此處應添加關於移動動畫的常見問題解答部分,內容與原文檔中的FAQs部分一致)
以上是使用CSS3實現60 fps移動動畫3的詳細內容。更多資訊請關注PHP中文網其他相關文章!