当前位置: 首页 > Web前端 > CSS

CSSAnimationsvsWebAnimationsAPI

时间:2023-03-30 13:40:34 CSS

作者:OllieWilliams原文:CSSAnimationsvsWebAnimationsAPIJavaScript中有一个原生的动画API叫做WebAnimationsAPI,本文简称为WAAPI。MDN上已经有很好的文档,DanWilson写了一篇很棒的文章系列。在本文中,让我们比较WAAPI和CSS动画。关于浏览器支持尽管本机浏览器支持仍然有限,但WAAPI具有全面而强大的polyfill,使其可以在今天的生产环境中使用。同样,可以在CanIUse中查看浏览器兼容性数据。然而,这并没有提供很好的信息来支持WAAPI的所有子特性。这是一个检查工具:请参阅DanWilson(@danwilson)在CodePen上进行的PenWAAPI浏览器支持测试。要在没有polyfill的情况下体验完整功能,请使用FirefoxNightly。WAAPI的基础如果您曾经使用过jQuery的.animate(),那么WAAPI的基本语法应该看起来很熟悉。varelement=document.querySelector('.animate-me');element.animate(关键帧,1000);animate方法接受两个参数:关键帧和持续时间。与jQuery相比的优势在于,它不仅内置于浏览器中,而且性能更好。第一个参数keyframes是一个对象数组,每个对象都是动画中的一个关键帧。看看这个简单的例子:varkeyframes=[{opacity:0},{opacity:1}];第二个参数duration是指你希望动画持续多长时间,在上面的例子中是1000毫秒。接下来让我们看一个更精彩的例子。使用WAAPI重新创建animistaCSS动画下面是从animista中提取的一些CSS代码,用于名为slide-in-blurred-top的入口动画。在实际PERF中看起来比这张GIF漂亮多了。以下是CSS中的关键帧:0%{transform:translateY(-1000px)scaleY(2.5)scaleX(.2);变换原点:50%0;过滤器:模糊(40px);不透明度:0;}100%{变换:translateY(0)scaleY(1)scaleX(1);变换原点:50%50%;过滤器:模糊(0);opacity:1;}WAAPI中的代码基本相同:varkeyframes=[{transform:'translateY(-1000px)scaleY(2.5)scaleX(.2)',transformOrigin:'50%0',filter:'blur(40px)',opacity:0},{transform:'translateY(0)scaleY(1)scaleX(1)',transformOrigin:'50%50%',filter:'blur(0)',opacity:1}];您可以看到将关键帧应用于需要动画的元素是多么容易:element.animate(keyframes,700);为简单起见,仅指定持续时间。但是,我们可以使用这第二个参数来传递更多的选项,至少还应该指定一个缓动效果。以下是所有可用选项的完整列表以及一些示例值:varoptions={iterations:Infinity,iterationStart:0,delay:0,endDelay:0,direction:'alternate',duration:700,fill:'forwards',easing:'ease-out',}element.animate(keyframes,options);使用这些选项,我们的动画将从头开始,没有任何延迟,在动画完成后来回循环。不幸的是,对于那些熟悉CSS动画的人来说,一些术语与我们习惯的不同。好处是打字快一点!使用缓动代替动画计时函数而不是动画迭代计数,而是迭代。如果我们希望动画永远重复,请使用Infinity而不是infinite。有点混乱,Infinity没有引号。Infinity是一个JavaScript关键字,而所有其他值都是字符串。我们使用毫秒而不是秒,这对于以前编写过大量JavaScript的人来说应该是一样的。(您也可以在CSS动画中使用毫秒,但很少有人这样做。)让我们仔细看看一个选项:iterationStart。当我第一次遇到iterationStart时,我有点困惑。为什么从指定的迭代开始而不是仅仅减少迭代次数?此选项在处理十进制数时很有用。例如,您可以将其设置为.5,动画会在播放到一半时开始。做一个完整的动画需要两半,所以如果迭代次数设置为1,iterationStart设置为.5,动画将从一半播放到动画结束,然后从开头开始播放动画,并在中间结束!值得注意的是,也可以设置迭代次数小于1。例如:varoption={iterations:.5,iterationStart:.5}这样,动画将从中间开始,玩到最后。endDelay:如果您将多个动画链接在一起,但您希望在一个动画的结束和后续动画的开始之间有一个间隙,endDelay很有用。这是PatrickBrosset解释它的有用视频。YouTube视频缓动缓动是任何动画中最重要的元素之一。WAAPI为我们提供了两种不同的方式来设置缓动-在我们的关键帧数组中或在我们的选项对象中。在CSS中,如果您使用animation-timing-function:ease-in-out,您可能希望动画缓慢开始并缓慢结束。事实上,这些缓动是在关键帧之间应用的,而不是整个动画。这允许对动画的感觉进行细粒度控制。WAAPI也提供了这个功能。varkeyframes=[{opacity:0,easing:'ease-in'},{opacity:0.5,easing:'ease-out'},{opacity:1}]值得注意的是在CSS和WAAPI中,没有应该传入最后一帧的缓动值,因为这不会有任何效果。但是很多人都会犯这个错误。有时为整个动画添加缓动效果会更直观。这在CSS中是不可能的,但现在在WAAPI中是可能的。varoptions={duration:1000,easing:'ease-in-out',}您可以在CodePen上看到这两种缓动之间的区别:单击我查看缓动与线性。值得注意的是CSS动画和WAAPI的区别还有一个区别:在CSS中默认是ease,而在WAAPI中默认是linear。ease实际上是ease-in-out的一个版本,当你想偷懒的时候,这是一个很好的选择。同时,线性是极其沉闷和死气沉沉的——一致的速度看起来机械和不自然。它被选为默认值,可能是因为它是最中性的选项。但是,在使用WAAPI时,最好使用easing,以免动画看起来呆板、机械。性能WAAPI提供与CSS动画相同的性能改进,尽管这并不一定意味着流畅的动画。希望这个API的性能优化能够让我们避免使用will-change和translateZ。但是,至少在当前的浏览器实现中,这些属性在处理性能问题时仍然是有帮助和必要的。但是,如果您的动画有延迟,则无需担心使用will-change。Web动画规范的主要作者向AnimationforWorkSlack社区提出了一些有趣的建议,希望他不介意我在这里重复一遍:如果有正向延迟,则无需使用will-change,因为浏览器会在delay开始的时候分层,在动画开始的时候就准备好了。WAAPI与CSS动画?WAAPI为我们提供了一组已经在CSS中实现的JavaScript语法。但是,不应将它们视为对手。如果我们坚持使用CSS来实现动画和过渡,那么我们就可以在WAAPI中为交互设置动画。Animate对象的.animate()方法不仅处理动画元素,它还返回一些东西。varmyAnimation=element.animate(关键帧,选项);在控制台查看的动画对象如果我们在控制台查看返回值,会发现这是一个动画对象。这为我们提供了各种功能,其中一些是不言自明的,例如myAnimation.pause()。我们可以通过更改animation-play-state属性来使用CSS动画实现类似的结果,但使用比element.style.animationPlayState="paused"更清晰的WAAPI语法。我们还可以使用myAnimation.reverse()轻松反转动画,再次对我们的脚本稍作改进以更改CSSanimation-direction属性。然而,到目前为止,使用JavaScript操作@keyframe并非易事。正如ChrisCoyier之前所写的那样,即使像重新启动动画这样简单的事情也需要一些技巧。使用WAAPI,我们可以简单地使用myAnimation.play(),如果动画已经完成,它将从头开始重播动画,或者如果我们暂停动画,则从中间开始迭代。我们甚至可以轻松地改变动画的速度。myAnimation.playbackRate=2;//加速myAnimation.playbackRate=.4;//使用一个小于1的数字来减慢速度element.getAnimations()//使用CSS或WAAPI返回应用于我们元素的任何动画或过渡如果您更喜欢使用CSS来定义和使用动画,getAnimations()允许API与@keyframes结合使用。您可以继续使用CSS完成大部分动画工作,然后在需要时从使用API中获益。getAnimations()将始终返回一个数组,即使只有一个动画用于DOM元素。我们为此使用单个动画对象。varh2=document.querySelector("h2");varmyCSSAnimation=h2.getAnimations()[0];我们也可以在CSS动画中使用网络动画API:)myCSSAnimation.playbackRate=4;myCSSAnimation.reverse();Promise和Event许多由CSS触发的事件,现在我们可以使用JavaScript代码来完成:animationstart、animationend、animationiteration和transitionend。以前通常需要监听动画或过渡的结束,以便从DOM中删除应用的元素。动画对象可以使用WAAPI来完成animationend或transitionend所做的事情:myAnimation.onfinish=function(){element.remove();}WAAPI为我们提供了两种选择:event和promise。动画对象的.finished方法在动画结束时返回一个承诺。以下代码是上述示例的承诺版本:myAnimation.finished.then(()=>element.remove())让我们看一个来自MozillaDeveloperNetwork的稍微复杂的示例。Promise.all接受一个promises数组,回调函数将在所有promises都实现后运行。可以看出element.getAnimations()返回的是一个动画对象数组。我们可以将数组中的所有动画对象映射到每个动画对象的.finished,从而得到需要的promise数组。在这个例子中,我们的函数只会在页面上的所有动画都完成后运行。Promise.all(document.getAnimations().map(animation=>animation.finished)).then(function(){//dosomethingcool})本文中提到的未来功能只是一个开始。从目前的规范和实现来看,未来将会有非常强大的动画API。

猜你喜欢