Курсор в моем текстовом редакторе отставал. Это довольно необычно, учитывая мою 8 -я керновую машину с 32 ГБ оперативной памяти. Отслеживая эту проблему, я обнаружил, что моя бегая игра потреблял 20-30% процессора во время холостого хода. Плохо! Оказывается, это были невидимые элементы, которые вращаются через CSS.
Это немного боль. Это означает, что нам нужно удалить все те элементы, которые исчезают, иначе они накапливаются и создают нагрузку. Здесь я покажу вам свое решение, используя React-верхние слои моей игры находятся в React, поэтому я использовал его. Я не предлагаю вам использовать React, чтобы решить эту проблему. Но если у вас есть анимированные элементы HTML, избавьтесь от них, если они не видны.
При загрузке сцен я отображаю индикатор в верхнем правом углу экрана.
Это исчезает, когда загрузка начинается и исчезает при выполнении загрузки. Я хотел избежать резкого перехода. Я занимался этим с классами CSS, чтобы скрыть и показать элемент. Мой код реагирования выглядит так:
Svgelement
Является ли мой компонент загружать файлы SVG и отображать их встроенные. А img
Тег будет выполнять одинаковую способ для этой настройки. Ключ – это IS_LOADING && 'Загрузка'
часть ClassName
атрибут. Это добавляет загрузка
Имя класса к элементу во время загрузки. Когда закончу загрузку, я удаляю имя класса.
Это CSS (SCSS):
.load-marker { &:not(.loading) { animation-name: fade-out; animation-fill-mode: forwards; animation-duration: 0.5s; animation-timing-function: ease-in-out; } &.loading { animation-fill-mode: forwards; animation-duration: 0.5s; animation-timing-function: ease-in-out; animation-name: fade-in; } @keyframes fade-out { from { opacity: 1; visibility: visible; } to { opacity: 0; visibility: collapse; } } @keyframes fade-in { from { opacity: 0; visibility: collapse; } to { opacity: 1; visibility: visible; } } }
У меня есть желание отступать в разглагольствование о системе анимации CSS! Я писал системы анимации и макета раньше, и Argh, это кислота, брошенная в мои глаза. Действительно, эта система имеет четкое добавление и удаление поддержки анимации, что делает всю эту настройку тривиальной. Но это CSS, и, увы …
Когда элемент теряет . загрузка
Класс Он будет переходить к прозрачному состоянию. Проблема, однако, возникла от некоторых других CSS:
.loader { svg { animation: rotation 6s infinite linear; overflow: visible; position: absolute; top: 20px; right: 20px; width: 70px; height: 70px; } @keyframes rotation { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } }
Это бесконечный
Бит – это проблема. Неузначнее, что мы исчезли непрозрачность до 0, анимация все еще работает! Firefox по -прежнему делает обновление стиля и макета, каждый кадр. Почему он в конечном итоге потребляет так много процессора, я понятия не имею. Chrome также потреблял процессор, но только около 10%. Примечание, 10% все еще смешной для статического экрана.
Я также мог бы «решить» проблему, не вращая элемент, если что -то не загружается. Это создает грубый переход, где значок резко перестает вращаться, исчезая. Нехорошо.
У меня есть два анимированных индикатора, загрузчик и отключенный значок, поскольку вы теряете соединение WebSocket с сервером. Я абстрагировал общий базовый компонент, чтобы справиться с ними одинаково. Вот как я его использую, для погрузчика:
export function Loader({ is_loading }) { return}
Это реализация:
function HideLoaderImpl({ is_loading, url, className }) { const [ timer_id, set_timer_id ] = React.useState(0) React.useEffect(() => { if( !is_loading && !timer_id ) { const css_duration = 1000 const new_timer_id = setTimeout( () => set_timer_id(0), css_duration ) set_timer_id(new_timer_id) } }, [is_loading]) // only trigger on an is_loading change const visible = is_loading || timer_id if(!visible) { return null } return () } const HideLoader = React.memo(HideLoaderImpl)
На первый взгляд, не очевидно, как это достигает отложенного удаления элемента. Генерация HTML ясна, когда видимый
это ложь, затем ничего не показывать. Когда true, отобразите элемент, как и раньше, с той же логикой для настройки загрузка
Название класса.
Если IS_LOADING
это правда, тогда видимый
будет правдой. Это простой случай. Но есть другое истинное условие, когда у нас есть timer_id
Анкет
settimeout
обратный вызов не делает ничего, кроме как очистить timer_id
когда это будет сделано. Сначала я подозревал, что мне придется отслеживать другую переменную, устанавливая на начале и в конце тайм -аута. Оказывается, все, что мне нужно знать, это то, есть ли вообще тайм -аут. Пока у меня есть таймер, я знаю, что не должен снимать элемент.
Список условий в React.useeffect
Важно здесь. Я предоставляю только IS_LOADING
– Я хочу, чтобы эффект запустил только если значение IS_LOADING
изменился. Некоторые руководства по стилю будут настаивать на том, чтобы я включил timer_id
(и set_timer_id
) также в списке. Этот подход определяет второй аргумент на Использовать
в качестве списка зависимостей, но это неверно. На самом деле это список значений, который в случае изменения, запустит эффект для работы снова. Документы React ясны по этому поводу. Тем не менее, скажите, что это список зависимостей, и рекомендуйте плагин Lint, который будет жаловаться на мой код. Эта рекомендация имеет смысл для UseCallback
и Usememo
, но не для Использовать
.
Добавление timer_id
В список будет неправильно. Когда таймер заканчивается, он устанавливает timer_id
до 0. Это изменение приведет к тому, что эффект снова запустит. Это тот случай, когда мы делаем «зависит» от timer_id
Значение, но мы не должны пересматривать, когда она меняется, так как это в конечном итоге создаст создание нового таймера.
В любом случае, этот простой код теперь делает то, что я хочу. Он определяет удаление DOM элемента до окончания анимации. Что ж, он определяет его на одну секунду, что достаточно длинное, чтобы охватить анимацию 0,5S CSS. Сложно сохранить эти времена синхронизировать – Больше кулака встряхивания в системе анимации CSS!
Если у вас есть взгляд на дефекты, там есть один. Значок загрузчика может быть удален слишком рано: когда IS_LOADING
становится истинным, затем ложным, затем через одну секунду снова становится истинной и ложной. Я не создаю новый таймер, если он уже существует, поэтому время отсрочки все еще будет от первого таймера. На практике это вряд ли произойдет, и влияние минимально. Исправление состоит в том, чтобы отменить существующий тайм -аут и всегда создавать новый.
Я никогда не получал очевидного ответа, почему мой курсор отставал. Были всевозможные приложения, приложения на холостые приложения, потребляющие 5-10% ЦП. Возможно, это реальная стоимость языков высокого уровня. Подробнее об этом в другой день. Я все еще надеюсь, что будущие приложения будут стремиться к меньшему использованию энергии.
На данный момент удалите все эти невидимые анимированные элементы HTML.
Оригинал: “https://dev.to/mortoray/highly-inefficient-invisible-animations-css-firefox-chrome-react-1g86”