」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > 降低效能的兩行 CSS(fps 到 ps)

降低效能的兩行 CSS(fps 到 ps)

發佈於2024-11-03
瀏覽:821

我最近發布了《學習廁所》,如果您看過它,您可能會注意到背景中的動畫,其中彩色圓圈在螢幕上對角移動。看起來像這樣:

它在 Chrome 和 Safari 上運行良好,但我注意到 Firefox 上的性能嚴重下降。

效能太差了,我直接在 Firefox 中停用了這個動畫。

動畫是如何運作的?

動畫是使用兩個嵌套的 div 建構的。外部 div 是網站 body 標籤的第一個子級。

    

.background-gradient 元素負責創建跨越其父容器的整個寬度和高度的漸變。像這樣:

The Two Lines of CSS That Tanked Performance (fps to ps)

外部 .background-mask 負責兩件事:

  1. 它將位置設為固定,並使容器填充視口的整個尺寸。
  2. 在漸變上創建點狀蒙版

這確保了點的顏色是其正下方漸變的顏色:

The Two Lines of CSS That Tanked Performance (fps to ps)

這是我上面描述的所有內容的 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 呈現到頁面(儘管我已在此處概述),它會經歷幾個階段。我們感興趣的三個階段是:

  • 佈局 - 當瀏覽器計算頁面上元素的大小和位置時
  • Paint - 繪製頁面的所有視覺方面,如圖像、顏色、陰影等
  • 複合 - 以正確的順序將元素層疊在一起

管道的順序如下所示:

佈局 → 繪製 → 合成

佈局和繪製過程可能會佔用大量 CPU 資源,因此嘗試減少 CSS 觸發管道中各個階段的次數非常重要*。 * 瀏覽器在某些方面可以透過優化某些屬性的效能來提供幫助,例如跳過渲染管道的整個階段,其他人可以利用硬體加速將計算從CPU轉移到GPU。

對某些屬性進行動畫處理,例如平移和不透明度,都可以避免觸發佈局並使用硬體加速。

遺憾的是,在設定蒙版位置動畫時並非如此。我查看了 Chrome,發現背景 div 的繪製計數在每個畫面上都在增加。幾秒鐘後,它已經觸發了超過 1,000 次油漆。

The Two Lines of CSS That Tanked Performance (fps to ps)

即使繪製數量如此之多,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 次。

The Two Lines of CSS That Tanked Performance (fps to ps)

眼尖的觀眾一定會發現一個問題。如果你還記得的話,背景的高度和寬度會填滿視窗。將背景向左和向上移動 24 像素,在視窗中留下這個空白區域。

The Two Lines of CSS That Tanked Performance (fps to ps)

解決這個問題很簡單,只需將蒙版尺寸添加到容器的寬度和高度即可:

.background-mask {
    --mask-size: 24px;

    width: calc(100%   var(--mask-size));
    height: calc(100%   var(--mask-size));
}

我們再在Firefox中看一下:

這可能不是一個完美的解決方案,但完成一個有趣的煙霧和鏡子 CSS技巧總是讓人有點滿足。

版本聲明 本文轉載於:https://dev.to/andrico1234/the-two-lines-of-css-that-tanked-performance-120fps-to-40fps-3lnj?1如有侵犯,請聯絡[email protected]刪除
最新教學 更多>
  • Python元類工作原理及類創建與定制
    Python元類工作原理及類創建與定制
    python中的metaclasses是什麼? Metaclasses負責在Python中創建類對象。就像類創建實例一樣,元類也創建類。他們提供了對類創建過程的控制層,允許自定義類行為和屬性。 在Python中理解類作為對象的概念,類是描述用於創建新實例或對象的藍圖的對象。這意味著類本身是使用...
    程式設計 發佈於2025-07-15
  • 如何使用Depimal.parse()中的指數表示法中的數字?
    如何使用Depimal.parse()中的指數表示法中的數字?
    在嘗試使用Decimal.parse(“ 1.2345e-02”中的指數符號表示法表示的字符串時,您可能會遇到錯誤。這是因為默認解析方法無法識別指數符號。 成功解析這樣的字符串,您需要明確指定它代表浮點數。您可以使用numbersTyles.Float樣式進行此操作,如下所示:[&& && && ...
    程式設計 發佈於2025-07-15
  • 如何處理PHP文件系統功能中的UTF-8文件名?
    如何處理PHP文件系統功能中的UTF-8文件名?
    在PHP的Filesystem functions中處理UTF-8 FileNames 在使用PHP的MKDIR函數中含有UTF-8字符的文件很多flusf-8字符時,您可能會在Windows Explorer中遇到comploreer grounder grounder grounder gro...
    程式設計 發佈於2025-07-15
  • Java為何無法創建泛型數組?
    Java為何無法創建泛型數組?
    通用陣列創建錯誤 arrayList [2]; JAVA報告了“通用數組創建”錯誤。為什麼不允許這樣做? 答案:Create an Auxiliary Class:public static ArrayList<myObject>[] a = new ArrayList<my...
    程式設計 發佈於2025-07-15
  • 在JavaScript中如何並發運行異步操作並正確處理錯誤?
    在JavaScript中如何並發運行異步操作並正確處理錯誤?
    同意操作execution 在執行asynchronous操作時,相關的代碼段落會遇到一個問題,當執行asynchronous操作:此實現在啟動下一個操作之前依次等待每個操作的完成。要啟用並發執行,需要進行修改的方法。 第一個解決方案試圖通過獲得每個操作的承諾來解決此問題,然後單獨等待它們: c...
    程式設計 發佈於2025-07-15
  • Java中如何使用觀察者模式實現自定義事件?
    Java中如何使用觀察者模式實現自定義事件?
    在Java 中創建自定義事件的自定義事件在許多編程場景中都是無關緊要的,使組件能夠基於特定的觸發器相互通信。本文旨在解決以下內容:問題語句我們如何在Java中實現自定義事件以促進基於特定事件的對象之間的交互,定義了管理訂閱者的類界面。 以下代碼片段演示瞭如何使用觀察者模式創建自定義事件: args...
    程式設計 發佈於2025-07-15
  • Python中何時用"try"而非"if"檢測變量值?
    Python中何時用"try"而非"if"檢測變量值?
    使用“ try“ vs.” if”來測試python 在python中的變量值,在某些情況下,您可能需要在處理之前檢查變量是否具有值。在使用“如果”或“ try”構建體之間決定。 “ if” constructs result = function() 如果結果: 對於結果: ...
    程式設計 發佈於2025-07-15
  • 如何同步迭代並從PHP中的兩個等級陣列打印值?
    如何同步迭代並從PHP中的兩個等級陣列打印值?
    同步的迭代和打印值來自相同大小的兩個數組使用兩個數組相等大小的selectbox時,一個包含country代碼的數組,另一個包含鄉村代碼,另一個包含其相應名稱的數組,可能會因不當提供了exply for for for the uncore for the forsion for for ytry...
    程式設計 發佈於2025-07-15
  • 圖片在Chrome中為何仍有邊框? `border: none;`無效解決方案
    圖片在Chrome中為何仍有邊框? `border: none;`無效解決方案
    在chrome 在使用Chrome and IE9中的圖像時遇到的一個頻繁的問題是圍繞圖像的持續薄薄邊框,儘管指定了圖像,儘管指定了;和“邊境:無;”在CSS中。要解決此問題,請考慮以下方法: Chrome具有忽略“ border:none; none;”的已知錯誤,風格。要解決此問題,請使用以下...
    程式設計 發佈於2025-07-15
  • 如何有效地轉換PHP中的時區?
    如何有效地轉換PHP中的時區?
    在PHP 利用dateTime對象和functions DateTime對象及其相應的功能別名為時區轉換提供方便的方法。例如: //定義用戶的時區 date_default_timezone_set('歐洲/倫敦'); //創建DateTime對象 $ dateTime = ne...
    程式設計 發佈於2025-07-15
  • 如何使用不同數量列的聯合數據庫表?
    如何使用不同數量列的聯合數據庫表?
    合併列數不同的表 當嘗試合併列數不同的數據庫表時,可能會遇到挑戰。一種直接的方法是在列數較少的表中,為缺失的列追加空值。 例如,考慮兩個表,表 A 和表 B,其中表 A 的列數多於表 B。為了合併這些表,同時處理表 B 中缺失的列,請按照以下步驟操作: 確定表 B 中缺失的列,並將它們添加到表的...
    程式設計 發佈於2025-07-15
  • 對象擬合:IE和Edge中的封面失敗,如何修復?
    對象擬合:IE和Edge中的封面失敗,如何修復?
    To resolve this issue, we employ a clever CSS solution that solves the problem:position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%)...
    程式設計 發佈於2025-07-15
  • Async Void vs. Async Task在ASP.NET中:為什麼Async Void方法有時會拋出異常?
    Async Void vs. Async Task在ASP.NET中:為什麼Async Void方法有時會拋出異常?
    在ASP.NET async void void async void void void void void的設計無需返回asynchroncon而無需返回任務對象。他們在執行過程中增加未償還操作的計數,並在完成後減少。在某些情況下,這種行為可能是有益的,例如未期望或明確預期操作結果的火災和...
    程式設計 發佈於2025-07-15
  • 為什麼在我的Linux服務器上安裝Archive_Zip後,我找不到“ class \” class \'ziparchive \'錯誤?
    為什麼在我的Linux服務器上安裝Archive_Zip後,我找不到“ class \” class \'ziparchive \'錯誤?
    class'ziparchive'在Linux Server上安裝Archive_zip時找不到錯誤 commant in lin ins in cland ins in lin.11 on a lin.1 in a lin.11錯誤:致命錯誤:在... cass中找不到類z...
    程式設計 發佈於2025-07-15
  • 左連接為何在右表WHERE子句過濾時像內連接?
    左連接為何在右表WHERE子句過濾時像內連接?
    左JOIN CONUNDRUM:WITCHING小時在數據庫Wizard的領域中變成內在的加入很有趣,當將c.foobar條件放置在上面的Where子句中時,據說左聯接似乎會轉換為內部連接。僅當滿足A.Foo和C.Foobar標準時,才會返回結果。 為什麼要變形?關鍵在於其中的子句。當左聯接的右側...
    程式設計 發佈於2025-07-15

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3