Эта статья написана гостем Гостевые посты SitePoint нацелены на привлечение интересного контента от известных авторов и спикеров сообщества JavaScript.
Один API, чтобы управлять ими всеми
Анимация в Интернете уже давно разделена на четыре разнородных лагеря:
- CSS-переходы и анимации очень производительны и обеспечивают создание ключевых кадров, но также требуют много времени для сборки и обеспечивают только базовое начальное и конечное управление в CSS и JavaScript . Это, как правило, сводит их к простой анимации ответа пользовательского интерфейса, циклам и анимации загрузки страницы.
- SMIL (Synchronized Multimedia Integration Language) очень мощный, но он также синтаксический и имеет неполную поддержку браузера. Он также ограничен управлением элементами исключительно в контексте SVG.
- JavaScript предлагает прямое управление элементами, но не понимает удобных для дизайнера функций, таких как ключевые кадры или замедление, и не имеет встроенной оптимизации и производительности CSS. Анимация Canvas API замечательна, но все еще не имеет понимания основ анимации и не может анимировать произвольные элементы DOM.
- Фреймворки JavaScript-анимации, такие как Greensock, пытаются преодолеть традиционные недостатки JavaScript, когда дело доходит до анимации, но имеют все связанные с этим недостатки фреймворков: загрузку страницы, производительность и изучение нового синтаксиса.
API веб-анимаций стремится объединить лучшие функции всех этих компонентов в единую унифицированную спецификацию , устраняя при этом недостатки, создавая естественное понимание ключевых кадров, упрощение и управление элементами в JavaScript, с той же производительностью на экране, что и CSS , Теперь, когда основные компоненты спецификации поддерживаются в Chrome и Firefox , а разработка либо анонсирована, либо ведется разработка в других браузерах, включая Safari и Edge , а также наличие надежного полифилла , пришло время серьезно подумать об API веб-анимации для создания веб-сайтов. страницы к жизни.
Ключевые кадры в JavaScript
Давайте рассмотрим один из самых простых примеров анимации ключевого кадра: перемещение элемента красного шара с одной стороны страницы на другую. Независимо от того, какую технику мы используем, элемент будет одинаковым:
<div id="redball"></div>
Как будет исходный CSS:
body { margin: 0; background: #000; overflow: hidden; min-height: 100vh; } #redball { background: red; width: 30vmin; height: 30vmin; border-radius: 50%; }
Я использовал vmin
измерения vmin
чтобы элемент всегда оставался симметричным, отвечая размеру области просмотра.
В CSS перемещение шарика с одной стороны страницы на другую потребует что-то вроде следующего:
@keyframes moveBall { from { transform: translateX(-20vw); } to { transform: translateX(100vw); } }
Эта анимация будет вызываться из объявления для элемента красного шара:
#redball { animation: moveBall 3s infinite; }
Результат, показанный в Codepen:
На данный момент есть несколько моментов, которые стоит отметить в отношении анимации, в том числе тот факт, что замедление (ускорение в начале и замедление в конце) автоматически встроено.
Введите API веб-анимации
Сохраняя HTML и начальные стили, давайте удалим CSS-анимацию и заменим JavaScript, который использует API веб-анимации для достижения той же цели:
var moveBall = document.getElementById('redball').animate([{ transform: 'translateX(-20vw)' }, { transform: 'translateX(100vw)' }], { duration: 3000, iterations: Infinity, easing: 'ease' });
Вы можете видеть, что анимация принимает почти тот же синтаксис, что и CSS, но представляет ее как объект с массивом, представляющим ключевые кадры. Нам не нужно явно декларировать ключевые кадры или from
— JavaScript автоматически распределит ключевые кадры для нас равномерно, хотя объявление также вполне возможно.
Анимация пока не будет проигрываться; как и в CSS, мы должны назвать это:
moveBall.play();
Часть синтаксиса ключевого кадра станет еще проще в будущих браузерах, поскольку аспекты синтаксиса преобразования CSS, которые были ранее значениями, станут доступны в виде свойств :
translateX: -20vw;
Это изменение спецификации уже доступно в Chrome Canary, но пройдет год или два, прежде чем новый синтаксис станет доступен во всех современных браузерах.
Есть еще несколько моментов, которые стоит отметить в скрипте:
- JavaScript берет время анимации в миллисекундах, а не в стандартных секундах CSS (миллисекунды также доступны в CSS, если к значению синхронизации добавляется
ms
). - API веб-анимации определяет число итераций в качестве
iterations
, а не свойство CSSinteration-count
(если он определен отдельно); Ключевое слово —Infinity
(с заглавной буквой I) для количества повторений, а не CSS дляinfinite
- В API веб-анимации ослабление по умолчанию является
linear
, поэтому в нашей демонстрации мы указываем значение по умолчанию для CSS-анимации.
Результат функционально эквивалентен анимации CSS.
Конечно, дублирование CSS-анимации, подобной этой, в JavaScript на самом деле не использует динамизм языка сценариев почти до максимальной производительности; чтобы продемонстрировать это, мы создадим гораздо более полнофункциональную анимацию.
Дилинг изображения
Некоторое время назад я был заинтересован в создании анимации, которая наносила серию изображений на веб-страницу, например, подбрасывая игральные карты на стол. Написание отдельных анимаций для каждой карты в традиционном CSS заняло бы много времени и всегда давало бы один и тот же результат. Вместо этого я использовал API веб-анимации как идеальный инструмент для работы.
Прогрессивные карты
Мы хотим, чтобы изображения отображались независимо от того, включен JavaScript или API веб-анимации или нет, поэтому начнем с добавления серии изображений на страницу:
<div class="shuffle expose"> <img src="bridgefog.jpg" alt> <img src="daisyface.jpg" alt> <img src="drowninghand.jpg" alt> <img src="firefigure.jpg" alt> <img src="shellhand.jpg" alt> <img src="waterfeet.jpg" alt> </div>
Я оставил значения alt
изображений пустыми, чтобы код был чистым; в рабочей версии они будут заполнены описаниями. Фотографии предоставлены .tafo. , используется в соответствии с лицензией Creative Commons Attribution-NoDerivs 2.0 .
Мы можем добавить немного CSS для добавления изображений с анимацией, если условие без JavaScript все еще выполняется:
@keyframes reveal { to { opacity: 1; } } .shuffle { min-height: 100vh; position: relative; } .shuffle img { width: 33%; opacity: 0; } .expose img { animation: reveal 1s forwards; }
Доставка отдельного изображения может быть отложена с помощью:
.expose img:nth-child(1) { animation-delay: 1s; } .expose img:nth-child(2) { animation-delay: 2s; } .expose img:nth-child(3) { animation-delay: 3s; } …
Естественно, эти объявления могут быть автоматизированы с помощью Sass или другого препроцессора.
Изображения будут иметь границу, если родительский элемент имеет class
webanim
, который будет применяться с JavaScript:
div.webanim img { border: 1.4vw solid #eee; }
JavaScript
Мы добавим скрипт в конец страницы. Мне понадобится несколько случайных значений в анимации, поэтому я создам функцию для их создания:
function getRandom(min, max) { return Math.random() * (max - min) + min; }
Затем я соберу контейнер изображений и все изображения внутри них, вместе с установкой переменной incrementor:
var imgContainer = document.querySelector(".expose"), imgSeq = document.querySelectorAll(".shuffle img"), i = 1;
Затем я удалю класс expose (оставив изображения с непрозрачностью 0
и не анимированные), поскольку CSS-анимация работает, только если контейнер имеет класс expose:
imgContainer.classList.remove("expose"); imgContainer.classList.add("webanim");
Класс webanim
размещает изображения с рамкой.
Основная часть скрипта выполняется в цикле forEach
внутри функции. Я вызову функцию, как только буду уверен, что все данные изображения загружены (в отличие от узлов изображения, просто появляющихся в DOM), используя отличный сценарий imagesLoaded
от David DeSandro :
function racknstack() { Array.prototype.forEach.call(imgSeq, function(photo) { setTimeout(function() { photo.style.position = "absolute"; photo.style.width = getRandom(33, 45) + "%"; photo.style.left = getRandom(-5, 65) + "%"; photo.style.top = getRandom(-6, 60) + "vh"; var animate = photo.animate([{ opacity: '0', transform: 'rotate(' + getRandom(-12, 12) + 'deg) scale(1.2)', boxShadow: '0 0 12px 12px rgba(0,0,0,.3)' }, { opacity: '1', transform: 'rotate(' + getRandom(-8, 8) + 'deg)', boxShadow: '0 0 6px 6px rgba(0,0,0,.3)' }], { duration: 2000, fill: 'forwards' }); }, 1800 * i) i++; }) }
Как и прежде, мы должны вызвать функцию, чтобы начать все с:
imagesLoaded(imgSeq, racknstack);
Результат:
В свою очередь, функция:
- устанавливает каждое изображение в абсолютную позицию;
- генерирует случайную ширину для изображения (в процентах, поэтому изображение остается плавным и отзывчивым)
- генерирует случайное положение для изображения (включая возможное отрицательное положение, означающее, что оно может появиться немного за пределами области просмотра)
- анимирует фотографию с помощью API веб-анимации. Ключевые кадры увеличивают изображение от
0
до полной непрозрачности, поворачивая изображение
forwards
необходимо, потому что мы хотим, чтобы изображения оставались в своем конечном состоянии после завершения анимации.
От силы к силе
Разработка API веб-анимации продолжается быстро:
- Текущий рабочий проект постоянно строится, и все большее число компонентов поддерживается в Chrome и Firefox.
- Существует превосходный, не зависимый от polyfill, который можно просто вставить на страницу, чтобы обеспечить поддержку браузеров, которые еще не реализовали спецификацию.
- Никто не был более публичным или вокальным в поддержку возможностей спецификации, чем Рэйчел Нэборс, у которого есть отличное введение в тему в блоге Mozilla Developer , а также несколько презентаций конференции и набор демонстрационных примеров CodePen, которые вы можете исследовать. , Вот краткий обзор ее работы в спецификации .
Вывод
Как вы можете видеть, API веб-анимаций позволяет нам перейти от конкретного декларативного, пошагового характера CSS-анимации к динамическому, обязательному подходу JavaScript, который обеспечивает выразительную, случайную, производительную анимацию.
Я хотел бы видеть ваши исследования в API веб-анимации, особенно на производственных сайтах: дайте мне знать в комментариях ниже!