Недавно я выпустил «Изучение туалетов», и если вы видели это, вы, вероятно, заметили анимацию на заднем плане, где цветные круги движутся по диагонали по экрану. Выглядит это так:
Он отлично работает в 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, я могу порекомендовать этот подробный пост Ахмада Шадида
Не все свойства CSS анимируются одинаково. Не вдаваясь в подробности того, как браузер отображает HTML на странице (хотя я обрисовал это здесь), отмечу, что он проходит через несколько этапов. Нас интересуют три этапа:
Порядок конвейера выглядит следующим образом:
Макет → Рисовать → Композитный
Процессы верстки и рисования могут быть ресурсоемкими, поэтому важно постараться уменьшить количество раз, когда ваш CSS запускает этапы конвейера*.* Браузер частично помогает, оптимизируя производительность для определенных свойств, некоторых пропустите целые этапы конвейера рендеринга, а другие смогут использовать аппаратное ускорение для переноса вычислений с ЦП на графический процессор.
Анимация определенных свойств, таких как перевод и непрозрачность, позволяет избежать запуска макета и использовать аппаратное ускорение.
К сожалению, при анимации положения маски это не так. Я взглянул на Chrome и увидел, что количество отрисовки фонового div увеличивается с каждым кадром. Через несколько секунд он уже вызвал покраску более 1000 раз.
Даже при таком большом количестве отрисовки анимация в 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 в минуту.
Внимательные зрители заметят проблему. Если вы помните, высота и ширина фона заполняют область просмотра. Сдвиг фона влево и вверх на 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