Управление воспроизведением веб-анимации в Chrome 39

Ранее в этом году в Chrome 36 появился метод element.animate как часть более широкой спецификации веб-анимации . Это позволяет создавать эффективные, нативные анимации, написанные в обязательном порядке, предоставляя разработчикам возможность создавать свои анимации и переходы с использованием наиболее подходящего для них подхода.

Для быстрого напоминания, вот как можно анимировать облако на экране с обратным вызовом по завершении:

var player = cloud.animate([
    {transform: 'translateX(' + start + 'px)'},
    {transform: 'translateX(' + end + 'px)'}
], 5000);
player.onfinish = function() {
    console.info('Cloud moved across the screen!');
    startRaining(cloud);
};

Это само по себе невероятно просто, и его стоит учитывать как часть вашего набора инструментов при создании анимации или переходов. Однако в Chrome 39 функции управления воспроизведением были добавлены к объекту AnimationPlayer , возвращаемому element.animate . Раньше после создания анимации можно было только вызвать cancel() или прослушать событие завершения.

Эти дополнения к воспроизведению открывают возможности того, что может сделать веб-анимация: превратить анимацию в инструмент общего назначения, а не предписывать переходы, т.е. «фиксированные» или предопределенные анимации.

Пауза, перемотка назад или изменение скорости воспроизведения

Начнем с обновления приведенного выше примера, чтобы приостановить анимацию при нажатии на облако:

cloud.addEventListener('mousedown', function() {
    player.pause();
});

Вы также можете изменить свойство playbackRate :

function changeWindSpeed() {
    player.playbackRate *= (Math.random() * 2.0);
}

Вы также можете вызвать reverse() , который обычно эквивалентен инвертированию текущей playbackRate (умноженной на -1). Однако есть несколько особых случаев:

  • Если изменение, вызванное методомverse reverse() приведет к фактическому завершению текущей анимации, currentTime также инвертируется — например, если совершенно новая анимация перевернута, вся анимация будет воспроизводиться задом наперед.

  • Если проигрыватель поставлен на паузу, анимация начнет воспроизводиться.

Очистка плеера

AnimationPlayer теперь позволяет изменять свое currentTime во время выполнения анимации. Обычно это значение будет увеличиваться со временем (или уменьшаться, если playbackRate отрицательное). Это может позволить управлять положением анимации извне, возможно, посредством взаимодействия с пользователем. Обычно это называют чисткой .

Например, если ваша HTML-страница представляет небо и вы хотите, чтобы жест перетаскивания изменил положение воспроизводимого в данный момент облака, вы можете добавить в документ несколько обработчиков:

var startEvent, startEventTime;
document.addEventListener('touchstart', function(event) {
    startEvent = event;
    startEventTime = players.currentTime;
    player.pause();
});
document.addEventListener('touchmove', function(event) {
    if (!startEvent) return;
    var delta = startEvent.touches[0].screenX -
        event.changedTouches[0].screenX;
    player.currentTime = startEventTime + delta;
});

Когда вы перетаскиваете документ, currentTime будет меняться, чтобы отразить расстояние от исходного события. Вы также можете возобновить воспроизведение анимации после завершения жеста:

document.addEventListener('touchend', function(event) {
    startEvent = null;
    player.play();
});

Это можно даже совместить с реверсивным поведением, в зависимости от того, где мышь была поднята со страницы ( комбинированная демонстрация ).

Вместо очистки AnimationPlayer в ответ на взаимодействие с пользователем его currentTime также можно использовать для отображения прогресса или статуса: например, для отображения статуса загрузки.

Полезность здесь в том, что AnimationPlayer позволяет установить значение, а базовая собственная реализация позаботится о визуализации прогресса. В случае загрузки продолжительность анимации может быть установлена ​​равной общему размеру загрузки, а currentTime — текущему загруженному размеру ( демо ).

Переходы и жесты пользовательского интерфейса

Мобильные платформы уже давно стали сферой обычных жестов: перетаскивания, скольжения, подбрасывания и тому подобного. Эти жесты, как правило, имеют общую тему: перетаскиваемый компонент пользовательского интерфейса, такой как «потянуть для обновления» представления списка или боковая панель, создаваемая с левой стороны экрана.

С помощью веб-анимации аналогичный эффект очень легко воспроизвести в Интернете — на настольном компьютере или на мобильном устройстве. Например, когда завершается жест, управляющий currentTime :

var steps = [ /* animation steps */ ];
var duration = 1000;
var player = target.animate(steps, duration);
player.pause();
configureStartMoveListeners(player);

var setpoints = [0, 500, 1000];
document.addEventListener('touchend', function(event) {
    var srcTime = player.currentTime;
    var dstTime = findNearest(setpoints, srcTime);
    var driftDuration = dstTime - srcTime;

    if (!driftDuration) {
    runCallback(dstTime);
    return;
    }

    var driftPlayer = target.animate(steps, {
    duration: duration,
    iterationStart: Math.min(srcTime, dstTime) / duration,
    iterations: Math.abs(driftDuration) / duration,
    playbackRate: Math.sign(driftDuration)
    });
    driftPlayer.onfinish = function() { runCallback(dstTime); };
    player.currentTime = dstTime;
});

Это создает дополнительную анимацию, выполняющую «дрейф». Это играет роль между тем, где жест был завершен, и нашей известной хорошей целью.

Это работает, поскольку анимации имеют приоритет, основанный на порядке их создания: в этом driftPlayer будет иметь приоритет над player. Когда driftPlayer завершится, он и его эффекты исчезнут. Однако его последнее время будет соответствовать текущему времени основного проигрывателя, поэтому ваш пользовательский интерфейс останется последовательным.

Наконец, если вам нравятся котята, есть демо-веб-приложение , демонстрирующее эти жесты. Он удобен для мобильных устройств и использует полифил для обратной совместимости, поэтому попробуйте загрузить его на свое мобильное устройство!

Идите вперед и element.animate

Метод element.animate сейчас просто великолепен — независимо от того, используете ли вы его для простых анимаций или используете возвращаемый AnimationPlayer другими способами.

Эти две функции также полностью поддерживаются в других современных браузерах посредством облегченного полифила . Этот полифил также выполняет обнаружение функций, поэтому по мере реализации этой спецификации поставщиками браузеров эта функция со временем будет становиться все быстрее и лучше.

Спецификация веб-анимации также будет продолжать развиваться. Если вы хотите поэкспериментировать с будущими функциями, они также доступны в более подробном полифиле: web-animations-next .