今年早些时候,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 中,播放控制功能已添加到 element.animate
返回的 AnimationPlayer
对象中。以前,创建动画后,您只能调用 cancel()
或监听完成事件。
这些播放添加使 Web Animations 可以实现多种可能性,即将动画转换为通用工具,而不是规范过渡,即“已修复”或预定义的动画。
暂停、快退或更改播放速度
首先,更新上例,以便在点击云时暂停动画:
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();
});
这甚至可以与反转行为结合使用,具体取决于鼠标从网页上抬起的位置(组合演示)。
除了拖动 AnimationPlayer
来响应用户互动之外,您还可以使用其 currentTime
来显示进度或状态,例如显示下载的状态。
这里的实用性是,AnimationPlayer
支持设置值,并让底层原生实现处理其进度可视化。在下载情况下,可以将动画的时长设置为总下载大小,并将 currentTime
设置为当前下载的大小(演示)。
界面转换和手势
一直以来,移动平台都是常见手势领域:拖动、滑动、滑动等。这些手势往往有着共同的主题:可拖动的界面组件,例如列表视图的“下拉刷新”功能。或从屏幕左侧编造的边栏。
借助 Web Animations,您可以轻松地在网络上(桌面设备或移动设备)上实现类似的效果。例如,当控制 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
优先于播放器。driftPlayer
完成后,它及其效果将会消失。不过,其最终时间将与底层播放器的 currentTime 一致,因此界面将保持一致。
最后,如果你喜欢小猫,这款演示 Web 应用可以很好地展示这些手势。它适合移动设备,并且使用 polyfill 来实现向后兼容性,因此请尝试在移动设备上加载该 polyfill!
接着,使用“element.animate”
现在,element.animate
方法完全不实用 - 无论您是要将其用于简单的动画,还是以其他方式利用其返回的 AnimationPlayer
。
其他现代浏览器也通过轻量级 polyfill 完全支持这两项功能。此 polyfill 还会执行功能检测,因此随着浏览器供应商实施该规范,此功能只会变得越来越快,越来越完善。
Web Animations 规范也会继续完善。如果您有兴趣试用即将推出的功能,现在也可以通过更详细的 polyfill: web-Animations-next 获取这些功能。