«Если рабочий хочет хорошо выполнять свою работу, он должен сначала заточить свои инструменты» — Конфуций, «Аналитики Конфуция. Лу Лингун»
титульная страница > программирование > Две строчки CSS, которые снизили производительность (от fps до ps)

Две строчки CSS, которые снизили производительность (от fps до ps)

Опубликовано 3 ноября 2024 г.
Просматривать:903

Недавно я выпустил «Изучение туалетов», и если вы видели это, вы, вероятно, заметили анимацию на заднем плане, где цветные круги движутся по диагонали по экрану. Выглядит это так:

Он отлично работает в 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, я могу порекомендовать этот подробный пост Ахмада Шадида

Что вызывает такое падение производительности?

Не все свойства CSS анимируются одинаково. Не вдаваясь в подробности того, как браузер отображает HTML на странице (хотя я обрисовал это здесь), отмечу, что он проходит через несколько этапов. Нас интересуют три этапа:

  • Макет — когда браузер рассчитывает размер и положение элементов на странице
  • Paint — рисует все визуальные аспекты страницы, такие как изображения, цвета, тени и т. д.
  • Композит — наложение элементов друг на друга в правильном порядке

Порядок конвейера выглядит следующим образом:

Макет → Рисовать → Композитный

Процессы верстки и рисования могут быть ресурсоемкими, поэтому важно постараться уменьшить количество раз, когда ваш CSS запускает этапы конвейера*.* Браузер частично помогает, оптимизируя производительность для определенных свойств, некоторых пропустите целые этапы конвейера рендеринга, а другие смогут использовать аппаратное ускорение для переноса вычислений с ЦП на графический процессор.

Анимация определенных свойств, таких как перевод и непрозрачность, позволяет избежать запуска макета и использовать аппаратное ускорение.

К сожалению, при анимации положения маски это не так. Я взглянул на Chrome и увидел, что количество отрисовки фонового div увеличивается с каждым кадром. Через несколько секунд он уже вызвал покраску более 1000 раз.

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

Даже при таком большом количестве отрисовки анимация в Chrome выглядит плавной. Однако в Firefox это кажется очень неприятным. К сожалению, я не смог найти способ измерить количество отрисовки в Firefox, поэтому любые предположения о низкой производительности Firefox, которые я делаю, являются чисто предположениями.

Что я заметил, так это то, что анимация хороша для небольших устройств, но ухудшается по мере увеличения размера экрана. Моя рабочая теория заключается в том, что Firefox не группирует триггеры макета для каждой маски 24x24, что приводит к снижению FPS при наличии большего количества масок 24x24. Опять же, здесь я могу быть совершенно не прав.

Как я это исправил?

Вместо анимации плохо оптимизированных свойств CSS, таких как маска-позиция, мне нужно было использовать более производительные свойства, такие как перевод.

Решение заключалось не в том, чтобы переместить маски на 24 пикселя, а в том, чтобы переместить весь фоновый элемент с помощью свойства перевода.

С абстрактной точки зрения анимация выглядит так:

Вот изменение в две строки в 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);
    }
}

Браузер больше не анимирует позицию маски, которая запускала макет в каждом кадре. Несмотря на то, что фон перемещается в каждом кадре, трансляция не запускает макет или отрисовку. Вы можете видеть, что единственный рисует дважды, а не 1000 в минуту.

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 Если есть какие-либо нарушения, свяжитесь с Study_golang. @163.com удалить
Последний учебник Более>

Изучайте китайский

Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.

Copyright© 2022 湘ICP备2022001581号-3