По большей части видео остаётся отделённым от веба, ограниченное iframe-ами, Flash-ем и закупоренное в крохотных вслывающих окошках по середине страницы. Это упущенная возможность для реализации идей веб-дизайнеров всего мира.
Но как интегрировать видео в приложение или на страницу? Как это будет выглядеть и как это воплотить в жизнь? В этой статье вы найдёте вдохновение, способ исполнения и технические особенности, чтобы начать использовать современное видео в вебе.
Видео, комбинированное с анимацией, является мощным инструментом для инновационного и неотразимого UX. Только представьте интерактивные скринкасты и подсказки, в которых элементы DOM-структуры перетекают по странице синхронно с подсказками. Почему бы не совместить видео с анимацией, чтобы показать новым пользователям ваше приложение? Как насчёт включить видео о том, что вы продаёте на странице сайта, заменив статичные «жипеги»? Стоит лишь немного увлечься и видео станет чем-то большим, чем просто мигающая бирка, вида «купи меня». Далее несколько прекрасных, вдохновляющих примеров видео, интегрированных в дизайн.
Новая промо-страница компании Apple для MacPro — это ошеломляющий пример видео, которое «вырвалось за рамки» и идеально вписалось в контент. Новый MacPro, акцентирует на себя внимание в центре страницы. Но стоит прокрутить колесом мыши, как он начинается вращаться и разбираться на составляющие, а плавно появляющиеся подсказки рассказывают о том, что вы сейчас наблюдаете.
Если вы осмелитесь на видео и анимацию в своём следующем проекте у вас не будет много источников, на которые можно опираться при разработке. Не канонической, простой в использовании, opensource библиотеки для синхронизации видео с анимацией не существует, поэтому все решения отличаются друг от друга. Нужно использовать Javascript или обойтись только CSS keyframe анимациями и transition-ами? Размещать видео на сервере проекта и использовать преимущества HMTL5 тега video
и события, привязанные к нему или воспользоваться YouTube-ом или Vimeo? И как, в конце концов, привязать анимации к видео?
Вместе мы найдём ответы на вышеупомянутые вопросы по мере того, как изучим микро JavaScript framework. Charlie.js обеспечит нас лёгкой в использовании API для синхронизации видео и CSS3 анимаций.
Лучший способ понять — сделать, так что поехали.
Нам нужен способ создания анимации и последующего её вызова в определённые моменты видео. Также нам нужно будет приостанавливать анимацию, если видео остановлено. И ещё способ переключения видео на разные временные участки.
Чтобы ограничить сферу применения данной статьи, мы будем использовать с Charlie.js только CSS анимации. JavaScript библиотеки анимации более гибкие и функциональные, но keyframe синтаксис привлекателен своей простотой для понимания, а его эффекты имеют аппаратное ускорение. Использовать для таких целей исключительно CSS анимации — хороший выбор для небольших проектов.
Чтобы сохранить простоту использования, Charlie.js поддерживает только одно видео на странице.
По мере того, как мы будем проходить через создание этой библиотеки помните, что используя этот фреймворк мы только изучаем CSS анимации и видео в вебе. Конечная цель — изучить, а не создать качественный код для продакта.
Для нашего небольшого фреймворка есть смысл разобраться с API в первую очередь. Иными словами, нам нужно понять, как кто-то использовал бы библиотеку, а потом написать скрипт исполнения API.
Библиотека видео и анимации может работать по разному, но основная загвоздка в том, как прикрутить анимацию к видео. Как разработчику указать какие анимации должны применяться к каким элементам и в какой момент времени видео это должно происходить?
Один из вариантов — слить данные в JSON или XML. Противоположным решением будет не разделять данные и поместить все конфигурации в вызовы функций на чистом JavaScript. Оба варианта хороши, но есть и нечто среднее.
Обычно, CSS анимация определяет в таблице стилей. Идеально, когда она определена для Charlie.js, не в JSON файле. Это имеет смысл и у этого решения есть преимущества. Когда анимация находится в таблице стилей, её можно протестировать без полной загрузки видео и библиотеки анимации.
Анимации привязаны к элементам, у которых есть data-атрибуты. Data-атрибуты же определяют имя анимации, а также задают время начала проигрывания.
Предположим, у вас есть CSS анимация под названием fade
, для плавного затухания (через понижение прозрачности), и другая анимация — fling
, для смещения элементов за пределы страницы. И вы хотите применить к блоку на странице обе эти анимации, продолжительностью 3 секунды в видео. Разметка должна выглядеть так:
<div class="charlie" data-animations="fade, fling" data-times="3, 3"> ... </div>
Charlie.js запустит данные анимации, когда видео дойдёт до 3-х секунд.
fade
и fling
анимации определены в таблице стилей, подключенной к документу.
А вот так fade
анимация может выглядеть в CSS (префиксы браузеров здесь не написаны, но всё же требуются для Chrome и Safari):
Класс .fade
— это то, через что Charlie.js запускает fade
анимацию, присваивая данный класс к анимируемому элементу.
Когда с API разобрались, следующим вопросом встаёт хостинг видео. Хостинг определяет, в какую оболочку будет обёрнуто видео и от этой оболочки будет зависеть, что мы сможем с ним сделать.
Видео, встроенное при помощи Flash или Silverlight ограничит варианты дизайна, поэтому сервис видео-хостинга должен поддерживать HTML5 video
тэг. video
тэг проще всего стилизовать и расположить на странице. Можно применить CSS фильтры и трансформации, а также CSS анимации прямо к видео. К тому же стандартные медиа-события надёжные и обеспечивают множество способ, чтобы привязать свой код к видео. Большим недостатком тега video
является совместимость. Он не работает в IE8. Ну и чёрт с ним!
Какие виды видео-хостинга должна поддерживать Charlie.js? Строение библиотеки делает возможной поддержку нескольких вариантов хостинга. Например, Popcorn.js (прекрасная библиотека для синхронизации видео и контента) поддерживает несколько вариантов хостинга и API. Но, чтобы сохранить её простоту, наша маленькая библиотека будет поддерживать только встроенный HTML5 video
тэг. Что-либо в iframe или flash-контейнере не будет поддерживаться.
Это, конечно, хорошо для Charlie.js, но что, если вы застряли (в прошлом десятилетии), поддерживая старые браузеры и вынужденны иметь дело с видео, завёрнутым в iframe? Большинство компаний видео-хостинга обладают приличным API. В крайнем случае, вы будете вынуждены использовать их API, чтобы синхронизировать свою анимацию. YouTube и Vimeo — самые популярные сервисы и оба предлагают обширные API для использования. Ещё есть такой прекрасный вариант, как Wistia, но он менее известный.
Если же хотите использовать исключительно video
тэг, но не хотите располагать видео на своём хостинге, обратите внимание на Vid.ly. Загрузите видео и Vid.ly перекодирует его в любой необходимый формат и выдаст универсальный URL для вставки в video
тэг, который автоматически выберет необходимый видео-формат, в соответствии с браузером пользователя.
JavaScript в большинстве данных сниппетов использует Underscore; такие вещи, как _.forEach
и _.toArray
являются функциями из этой библиотеки. Underscore поощряет функциональный стиль программирования, который может удивить вас, если вы никогда не сталкивались с ним ранее. Но немного потраченного на изучение времени сэкономит уйму времени и строк кода в будущем. Лучше не проверять это на своём опыте. Далее вы встретите комментарии в коде, которые будут описывать, что происходит. Должно быть достаточно легко для понимания.
Ещё один нюанс: этот код запустится в большинстве современных браузеров, но никто не делал его кроссбраузерным для примера. Если ваш проект требует синхронизацию CSS анимации и видео, а также работоспособности во всех браузерах, то эта библиотека не решит вашу задачу. Но зато она прекрасно подходит для проектов, рассчитанных только на современные веб-клиенты. И даже не смотря на это ограничение большая часть данного материала всё ещё стоит того, чтобы её изучить.
JavaScript — это клей между видео и CSS анимацией. Нет способа соединить анимацию с видео на чистом CSS. Анимация не начнётся, пока стиль не применён и CSS предоставляет несколько вариантов вызова дополнительных стилей (таких как :hover
). Но для синхронизации анимации с видео нам понадобится ставить на паузу, останавливать, продолжать воспроизведение, переходить на середину видео и даже проигрывать анимации (вместе с видео) в обратную сторону.
Всё это можно реализовать через JS. Итак, первый шаг — получить CSS анимацию из таблицы стилей в JavaScript. Любая анимация делится на 2 части:
первая — keyframe и свойства, используемые для настройки поведения анимации, такие как длительность, количество повторений и направление;
вторая часть — это то, что будет запускать анимацию. Charlie.js нужны обе части в таблице стилей.
Первое, что нужно сделать, это написать функцию для поиска в таблицах стилей, которые загружены на страницу:
Функция findRules
проходит через каждое выражение каждой таблицы стилей и возвращает список выражений, который совпадает с переданными в функцию matches
. Чтобы получить все keyframe выражения мы передаём функцию в findRules
, которая проверяет, является ли выражение keyframe-ом:
С этой точки зрения у нас уже есть keyframe в JavaScript, но нам всё ещё нужны другие стили анимаций, определяющие продолжительность, цикличность, направление и прочее.
Чтобы найти все эти свойства мы опять используем findRules
чтобы проверить каждое выражение в каждой таблице стилей. В этот раз функция matches
, которую мы передадим, проверит есть ли хоть в одном в выражении свойство animationName
.
Функция animationsName
нужна для обработки префиксов, поскольку свойство animationsName
всё ещё требует префиксы в некоторых веб-браузерах. В результате функция выглядит вот так:
После того, как определяется необходимый префикс, имя кэшируется и используется при будущих его поисках.
Когда ключевые keyframe и стили анимаций собраны они передаются во helper class и хранятся в Charlie.js для дальнейшего использования.
Информация о времени прилагается к анимируемому элементу через data-атрибут. Итак, нам придётся перелопатить документ и выудить эту информацию. Любой элемент, который нужно анимировать помечается классом charlie
, и это сильно облегчает на поиск:
Листинг выше сохраняет о времени в объект, используя имя анимации, как ключ, к которому привязывается список времени и элементов. Этот объект используется для создания нескольких Animation
объектов, которые затем преобразуются в различные структуры данных, чтобы сделать их проще и чтобы быстрее можно было отыскать необходимую для проигрывания анимацию в большом цикле.
Самым важным в Charlie.js является цикл, который запускается всякий раз, когда проигрывается видео. Этот цикл создаётся при помощи requestAnimationFrame
.
Функция requestAnimationFrame
предназначена специально для оптимизации любого вида анимации, таких, как DOM манипуляции, прорисовка графики и WebGL. Это сложнее, чем просто setTimeout
, но функция откалибрована для связи стадий анимации и компоновки их воедино, что делает результат более производительным. Также она является выгодным вариантом для энергосбережения на мобильных устройствах, так как полностью останавливает ход анимации, когда пользователь переключает вкладки.
Цикл начинает работать, когда запускается видео и останавливается вместе с видео. Charlie.js также нужно дать понять, видео остановилось или мы просто переключили куда-то на середину. Для каждого из этих событий требуется немного разный подход.
Пока видео проигрывается, цикл продолжается. Каждая итерация запускает следующий код:
Всё, что мы сделали на данный момент, было для поддержки этих нескольких строк кода. Переменная seconds
— это просто значение video.currentTime
, округлённое до одной десятой секунды. Значение bySeconds
создано из информации о времени, взятой из HTML — просто это самый быстрый способ получить список анимаций, чтобы запустить его в данный момент времени. Массив running
— это список анимаций, которые сейчас воспроизводятся. Цикл requestAnimationFrame
действительно быстро действенный и запускается очень много раз в секунду, а Charlie.js поддерживает максимальную частоту обновления только раз в одну десятую секунды.
Итак, если какая-то анимация начинается на 2-й секунде, requestAnimationFrame
попытается запустить её несколько раз, пока видео идёт следующую десятую долю секунды. Чтобы предотвратить повтор анимации в течении этой одной десятой секунды её добавляют в массив running
, в котором находятся проигрываемые в данный момент анимации.
Чтобы запустить CSS анимацию, просто добавьте свойства анимации в стили элемента. Проще всего сделать это, добавив класс анимации в classList
и это именно то, что делает метод start
.
Имя анимации совпадает с именем класса, соответственно.
Когда видео останавливается анимация должна останавливаться вместе с ним. Есть замечательный простой способ реализации, используя CSS анимации: мы просто задаём значению элемента animationPlayState
статус paused
.
Единственный хитрость состоит в том, чтобы отслеживать, какие анимации были приостановлены, чтобы можно было продолжить их, когда видео опять будет проигрываться:
Что, если кто-то пролистает видео и перепрыгнет в середину анимации? Как запустить анимацию посередине видео? Свойство animationDelay
— это именно то, что нам нужно. Обычно animationDelay
устанавливают позитивное числовое значение. Если нужно, чтобы анимация началась через 3 секунды, после того, как её стили будут применены, то нужно установить animationDelay
на 3s
. Но если установить animationDelay
отрицательное значение, то анимация перепрыгнет в середину. К примеру, если анимация длится 3 секунды, а нам нужно, чтобы анимация началась со второй секунды, зададим animationDelay
значение -2s
.
Каждый раз, когда пользователь ткнёт на середину видео, Charlie.js нужно остановить все анимации, которые проигрывались в данный момент, понять, что должно воспроизводится теперь, а потом присвоить подходящее animationDelay
значение. Вот, собственно, хай-левел код:
Функция animationsToStart
ищет в списке анимаций что-нибудь, что должно быть проиграно в данный момент. Если конечное время больше текущего, а время начала меньше текущего, анимация запустится.
timeModel
— это список анимаций, отсортированный по времени окончания анимации. Это код ищет анимации, которые начинаются раньше текущего времени и заканчиваются после. Массив toStart
содержит все анимации, которые должны начаться прямо сейчас.
Их значения передаются в хай-левел код, который считает и задаёт задержку в функции setDelay
.
Параметр seconds
— это текущее время видео. Предположим, что видео длится 30 секунда, а анимация начинается на 24-й секунде и длится 10 секунд. Если мы зададим задержку -6s
, то анимация начнётся со своей 6-й секунды и продлится оставшиеся 4 секунды.
Мы рассмотрели, как использовать requestAnimationFrame
чтобы создать оптимизированный механизм для анимаций, как собрать keyframe-ы и стили из таблиц стилей, как запускать и останавливать анимации вместе с видео и даже как проигрывать CSS анимации с середины. Но в этой статье было пропущено немало промежуточного кода. Charlie.js — это только часть из сотен строк кода, но фрейворк opensource-ный и хорошо прокомментирован.
Вы, конечно, можете использовать этот ресурс, но с некоторыми оговорками:
requestAnimationFrame
. Он не проигрывает видео, если вкладка с ним не активна. Это может запутать пользователей, которые переключаются между вкладками.Какие-то из этих ограничений можно легко исправить, но Charlie.js был создан для очень ограниченного спектра действий.
Вослользуйтесь удобным для вас способом связи или приезжайте к нам в офис, где вас ждет чашечка кофе