Chrome 39 中的网络动画播放控件

今年早些时候,Chrome 36 引入了 element.animate 方法,作为更广泛的 Web 动画规范的一部分。这样一来,开发者就可以以命令式方式编写高效的原生动画,从而选择使用最适合他们的方法来构建动画和转场效果。

下面的示例快速回顾了如何在屏幕上呈现云的动画效果,并在完成时发出回调:

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 中,播放控制功能已添加到 element.animate 返回的 AnimationPlayer 对象中。以前,创建动画后,您只能调用 cancel() 或监听 finish 事件。

这些播放功能的新增扩展了 Web 动画的可能性,将动画转变为通用工具,而不是对转场进行规范,例如“固定”或预定义动画。

暂停、快退或更改播放速度

首先,我们更新上面的示例,以便在点击云朵时暂停动画:

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

您还可以修改 playbackRate 属性:

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

您还可以调用 reverse() 方法,这通常等同于反转当前的 playbackRate(乘以 -1)。不过,也有一些特殊情况:

  • 如果 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();
});

这甚至可以与反向行为结合使用,具体取决于鼠标从页面上移除的位置(组合演示)。

您可以使用 currentTime 来显示进度或状态,而不是在响应用户互动时清除 AnimationPlayer,例如显示下载状态。

这里的效用在于,AnimationPlayer 允许设置值,并让底层原生实现负责处理其进度可视化。在下载用例中,动画的持续时间可以设置为总下载大小,并将 currentTime 设置为当前下载大小(演示)。

界面转换和手势

移动平台长期以来一直是常见手势的天下:拖动、滑动、快速滑动等。这些手势通常具有共同的主题:可拖动的界面组件,例如列表视图的“拉动以刷新”或从屏幕左侧拉出的边栏。

借助 Web 动画,您可以非常轻松地在桌面设备或移动设备上复制类似的 Web 效果。例如,当控制 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 完成后,它及其效果将消失。不过,其最终时间将与底层播放器的 currentTime 一致,因此您的界面将保持一致。

最后,如果您喜欢小猫,可以参阅演示 Web 应用,了解这些手势。该应用适用于移动设备,并使用了 polyfill 以实现向后兼容性,因此请尝试在移动设备上加载该应用!

继续使用 element.animate

element.animate 方法目前非常强大,无论您是将其用于简单的动画,还是以其他方式利用其返回的 AnimationPlayer,都能发挥出色效果。

其他新型浏览器也通过轻量级 polyfill 完全支持这两项功能。此 polyfill 还会执行功能检测,因此随着浏览器供应商实现规范,此功能将会随着时间推移变得更快、更好。

Web 动画规范也将不断发展。如果您有兴趣试用即将推出的功能,现在也可以在更详细的 polyfill:web-animations-next 中使用这些功能。