Это урок о производительности JavaScript, который вы уже знаете, но всегда забываете. По крайней мере, я
Вы можете полностью использовать JavaScript для создания производительной анимации со скоростью 60 кадров в секунду. Даже с тысячами элементов, движущихся в каждом кадре вашей анимации.
ПРИМЕЧАНИЕ. Это кросс-пост из моего информационного бюллетеня. Я публикую каждое электронное письмо через две недели после его отправки. Подпишитесь, чтобы получать больше подобного контента раньше прямо в свой почтовый ящик! 💌
Несколько лет назад (время летит незаметно) я использовал React, Redux и Canvas, чтобы протолкнуть генератор частиц через 20 000 элементов. Даже на мобильном телефоне.
Основная идея звучит так:
- поместите все, что вы анимируете, в состояние
- изменить состояние 60 раз в секунду
- пусть React повторно отрендерит
- анимация!
Дает вам полный контроль. Иногда даже слишком. Для более легкого подхода вы можете использовать переходы D3. Особенно полезно, если вы уже создаете датавиз или что-то в этом роде.
Около 10 строк кода и у вас есть Декларативные переходы D3 с реакцией 👇
Отлично работает 👌
Рекурсия DOM сложна для движка React
Но потом вы делаете что-то глупое. Как визуализировать древовидную структуру данных с помощью рекурсии.
Вот как выглядит использование переходов D3 для анимации всего 536 элементов, когда эти элементы глубоко вложены.
Да, это с производственной сборкой React. Не очень помогает.
Вы можете узнать больше о том, как работает этот флеймеграф, в этом уроке Tiny React & D3 flamegraph. Дело в том, что он декларативен, прост в использовании и имеет переходы D3 для анимации.
Но спектакль ужасный ☹️
Проблема в том, что распространение информации через глубоко вложенное дерево - это чуть ли не худший сценарий для движка React. Это означает, что огромная часть дерева помечена для обновлений и нет возможности для оптимизации.
Есть два способа решить эту проблему:
- Реорганизуйте код, чтобы он использовал плоскую структуру DOM / React.
- Вместо этого используйте переходы CSS
Первый вариант отличный. Модифицированная версия популярной в компьютерных классах задачи оптимизация хвостовой рекурсии.
Хвостовая рекурсия - это когда вы вызываете свою функцию как последнюю операцию вашей функции. Рекурсия происходит последней.
const Flamegraph = (...) => ( <g> <rect> <Flamegraph> </g> )
Вы, вероятно, всегда можете размотать их на петли. Петли имеют лучшую производительность.
Во многих других языках компилятор выполняет эту оптимизацию за вас. Вы пишете хвостовую рекурсию, а компьютер выполняет цикл.
Интересно, сможет ли React это сделать? Я должен спросить. Вероятно, это не то, о чем будет заботиться достаточное количество людей.
Делать это вручную громоздко.
CSS-анимация спешит на помощь
Калле Отт услужливо решил проблему с анимацией CSS. Потому что Калле Отт потрясающий.
Использование переходов CSS отлично работает 👇
Браузеры безумно хороши в анимации с помощью CSS. Часть движка рендеринга браузера, работающая, если это вообще возможно, на графическом процессоре, отлично работает.
Вы в любом случае уже выполняете переходы, не так, как будто вам нужен контроль над JavaScript. 🤷♀️
К тому же это довольно просто сделать.
Определите несколько переходов
const transitionTime = "250ms"; const transitionCurve = "cubic-bezier(0.85, 0.69, 0.71, 1.32)"; const widthTransition = `width ${transitionTime} ${transitionCurve}`; const transformTransition = `transform ${transitionTime} ${transitionCurve}`;
Примените их к нужным элементам с помощью JavaScript.
componentDidUpdate() { const { width, x, y } = this.props; d3select(this.gRef.current).attr("transform", `translate(${x}, ${y})`); this.hideLabel(); } // render <g transform={`translate(${x}, ${y})`} style= onClick={this.onClick} ref={this.gRef} >
Тот же API, что и раньше: измените x
и width
, когда вам нужно обновить. За исключением того, что теперь переход x
обрабатывается transformTransition
, а переход ширины запускается в componentDidUpdate
с меньшим количеством строк, чем раньше.
Урок выучен. Спасибо, Калле 👌
В других новостях
Выбор стажера идет хорошо. На прошлой неделе у нас был веб-семинар, на котором я объяснил новый контекстный API React и ответил на кучу вопросов. Было весело. Вот резюме.
Придумывать это и принимать важные решения отнимали большую часть моей недели. Подробнее об этом в блоге на следующей неделе :)
Я обещаю, что "Learn While You Poop" скоро вернется в эфир. Я знаю, что уже говорил это несколько раз, но сейчас контент распланирован, и буфер накапливается. 🤞
Несколько крутых вещей
Вот несколько интересных моментов за неделю:
- Эта красивая история о том, каким крутым был Фейнман
- Дэйв Седдиа опубликовал отличный справочник по React Native / тушеной свинине.
- Это отличное руководство по алгоритмической сложности. Всегда хорошо иметь чувство предположения об этом.
- Отличный пост о D3, Проблема с D3
- Есть актуальный набор данных о чемпионатах мира с API. Захотелось построить что-нибудь крутое, но я не знаю что 🤔
Ваше здоровье,
~ Swizec
PS: Вас заинтересует платный вебинар по React & D3? Подобно моим 7-часовым семинарам, но короче и намного дешевле. Я разрабатываю новый материал для обновления книги / курса и хочу его опробовать. Оставьте мне комментарий!
P.S. Если вам это нравится, обязательно подпишитесь, подпишитесь на меня в Twitter, купите мне обед и поделитесь этим со своими друзьями. 😄