我最近發布了《學習廁所》,如果您看過它,您可能會注意到背景中的動畫,其中彩色圓圈在螢幕上對角移動。看起來像這樣:
它在 Chrome 和 Safari 上運行良好,但我注意到 Firefox 上的性能嚴重下降。
效能太差了,我直接在 Firefox 中停用了這個動畫。
動畫是使用兩個嵌套的 div 建構的。外部 div 是網站 body 標籤的第一個子級。
.background-gradient 元素負責創建跨越其父容器的整個寬度和高度的漸變。像這樣:
外部 .background-mask 負責兩件事:
這確保了點的顏色是其正下方漸變的顏色:
這是我上面描述的所有內容的 CSS:
.background-mask { --mask-size: 24px; /* Position Styles */ position: fixed; width: 100%; height: 100%; z-index: -1; /* Mask Styles */ mask-image: radial-gradient(black 2px, transparent 2px); mask-size: var(--mask-size) var(--mask-size); mask-position: 0px 0px; animation: mask-move 3s infinite linear; } .background-gradient { background: var(--red); background-image: var(--gradient); width: 100%; height: 100%; } @keyframes mask-move { 0% { mask-position: 0px 0px; } 100% { mask-position: var(--mask-size) var(--mask-size); } } @media (prefers-reduced-motion: reduce) { .hero-background-mask { animation: none; } }
如果您有興趣了解有關 CSS 中蒙版的更多信息,那麼我可以推薦 Ahmad Shadeed 撰寫的這篇綜合文章
並非所有 CSS 屬性的動畫效果都是一樣的。無需過多討論瀏覽器如何將 HTML 呈現到頁面(儘管我已在此處概述),它會經歷幾個階段。我們感興趣的三個階段是:
管道的順序如下所示:
佈局 → 繪製 → 合成
佈局和繪製過程可能會佔用大量 CPU 資源,因此嘗試減少 CSS 觸發管道中各個階段的次數非常重要*。 * 瀏覽器在某些方面可以透過優化某些屬性的效能來提供幫助,例如跳過渲染管道的整個階段,其他人可以利用硬體加速將計算從CPU轉移到GPU。
對某些屬性進行動畫處理,例如平移和不透明度,都可以避免觸發佈局並使用硬體加速。
遺憾的是,在設定蒙版位置動畫時並非如此。我查看了 Chrome,發現背景 div 的繪製計數在每個畫面上都在增加。幾秒鐘後,它已經觸發了超過 1,000 次油漆。
即使繪製數量如此之多,Chrome 上的動畫也感覺很流暢。然而,在 Firefox 上感覺超級卡頓。令人煩惱的是,我找不到測量 Firefox 上的繪製計數的方法,因此我對 Firefox 糟糕性能所做的任何假設都純粹是猜測。
我注意到動畫對於小型設備來說很好,但隨著螢幕尺寸的增加而變得更糟。我的工作原理是,Firefox 不會對每個 24x24 蒙版進行批次佈局觸發器,這會導致當存在更多 24x24 蒙版時 FPS 下降。再說一次,我在這裡可能完全錯了。
我需要依靠效能更高的屬性,例如translate,而不是對優化不佳的CSS屬性(如mask-position)進行動畫處理。
解決方案不是將蒙版移動 24px,而是使用平移屬性移動整個背景元素。
從抽象的角度來看,動畫是這樣的:
CSS 中的兩行更改:
/* --mask-size = 24px */ @keyframes mask-move { 0% { transform: translate(calc(var(--mask-size) * -1), calc(var(--mask-size) * -1)); } 100% { transform: translate(0px, 0px); } }
瀏覽器不再對蒙版位置進行動畫處理,這會在每個畫面上觸發佈局。即使背景在每一幀上移動,透過翻譯它也不會觸發佈局或繪製。您可以看到,唯一的繪製次數為每分鐘 1,000 次。
眼尖的觀眾一定會發現一個問題。如果你還記得的話,背景的高度和寬度會填滿視窗。將背景向左和向上移動 24 像素,在視窗中留下這個空白區域。
解決這個問題很簡單,只需將蒙版尺寸添加到容器的寬度和高度即可:
.background-mask { --mask-size: 24px; width: calc(100% var(--mask-size)); height: calc(100% var(--mask-size)); }
我們再在Firefox中看一下:
這可能不是一個完美的解決方案,但完成一個有趣的煙霧和鏡子 CSS技巧總是讓人有點滿足。
免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。
Copyright© 2022 湘ICP备2022001581号-3