前言
接着上文往下介绍,上篇文章我们对JS原生动画和贝塞尔曲线有了一个详细的认识,基于定时器或动画帧,我们可以实现元素的动画缓动,本文将分享浏览器中功能强大的Animations API,有兴趣的朋友请接着往下看吧
介绍
Web Animations API(简称WAAPI)于2016年成为Web标准的一部分,它的功能比之前提到的动画要丰富的多,它的核心理念是时间轴和动画效果。它提供了一组功能强大的方法和属性,用于定义、操作和管理动画效果。
时间轴(Timeline)是WAAPI中的核心概念之一。它类似于一个全局时钟,用于管理和协调所有正在运行的动画。通过时间轴,开发者可以控制动画的播放、暂停、重置等操作。
动画效果(Animation Effect)指的是要应用到动画目标上的转换或变化。WAAPI提供了多种类型的动画效果,如位移(translate)、缩放(scale)、旋转(rotate)等。开发者可以使用这些效果来创建各种动画效果。
基本使用
关键帧
还记得之前的CSS关键帧吗?使用from to或者百分比来定义动画阶段的效果,在JS中使用KeyframeEffect类可以创建关键帧动画
const box = document.querySelector(".box") const keyframes = [ { left: 0 }, { left: '100px' } ]; const keyframe = new KeyframeEffect(box, keyframes, 1000);
上述代码中,KeyframeEffect类接收三个参数:第一个是目标标签,第二个是关键帧,第三个是动画时间
KeyframeEffect的三种类的声明
- KeyframeEffect(keyframeEffect):复制关键帧配置
- KeyframeEffect(element, keyframes, duration):在标签element上生成新的动画,关键帧为keyframes,持续duration毫秒
- KeyframeEffect(element, keyframes, options):在标签element上生成新的动画,关键帧为keyframes,动画配置options
keyframes
关键帧的写法有两种,分别是数组的方式和样式对象的写法
- 数组
const keyframes = [ { left: 0, top: "50px" }, { left: '100px', top: "100px" }, { top: "150px" } ];
- 对象
const keyframes = { left: [0, '100px', '100px'], top: ["50px", "100px", "150px"] }
options
KeyframeEffect的第三个参数类型是数字或options配置项,数字代表动画时长,options则有以下属性:
- delay:动画开始之前的延迟时间,以毫秒为单位,默认值为0。对应css的animation-delay
- direction:动画的播放方向,可以是 "normal"(正常播放)、"reverse"(反向播放)、"alternate"(交替播放)或 "alternate-reverse"(交替反向播放)。默认值为 "normal"。对应css的animation-direction
- duration:动画的持续时间,以毫秒为单位,默认值为0。对应css的animation-duration
- easing:动画的缓动函数,可以使用 CSS 缓动函数,如 "linear"、"ease"、"ease-in" 等,或者自定义的缓动函数。默认值为 "linear"。对应css的animation-timing-function
- endDelay:动画结束后的延迟时间,以毫秒为单位,默认值为0。
- fill:动画在非活动时间段的行为,可以是none(默认,动画结束后不会保留任何效果)、forwards(动画结束后保持最后一帧的效果)或backwards(动画开始前应用第一帧的效果)。也可以是both,表示同时应用forwards和backwards的效果。对应css的animation-fill-mode
- iterationStart:动画的迭代开始位置,以小数表示(例如,0.5表示从动画的中间位置开始迭代),默认值为0。
- iterations:动画的迭代次数,可以是一个正整数或Infinity(无限循环),默认值为1。对应css的animation-iteration-count
- keyframes:动画的关键帧,可以是一个关键帧规则对象或关键帧数组。
- playbackRate:用于控制动画播放速率的属性。它可以用于加速或减慢动画的播放速度。
- composite(CompositeOperation):动画的合成行为。可以是replace或add。默认值为replace。replace表示动画将覆盖目标属性的当前值,而add表示动画将与目标属性的当前值叠加。
- iterationComposite(IterationCompositeOperation):动画迭代之间的值合成行为。可以是replace或accumulate。默认值为replace。replace表示每次迭代时动画的值将替换目标属性的当前值,而accumulate表示每次迭代时动画的值将累积到目标属性的当前值上。
- pseudoElement:应用动画的伪元素。可以是一个字符串,表示伪元素的名称,例如before或after,或者可以是null,表示应用于主元素而非伪元素。
示例
<!DOCTYPE html> <html lang="CH"> <head> <meta charset="UTF-8" /> <title>webAnimationsAPI</title> <style> html, body { width: 100%; height: 100%; position: relative; } .box { width: 200px; height: 200px; top: 50px; position: absolute; background: lightblue; } .box::after { width: 100px; height: 100px; content: ""; left: 50px; position: absolute; background: lightcoral; } </style> </head> <body> <div class="box"></div> <button onclick="playHandler()">开始</button> <script> const box = document.querySelector(".box") const keyframes = [ { transform: "rotate(0)" }, { transform: "rotate(180deg)" }, { transform: "rotate(360deg)" }, ]; const options = { delay: 500,// 延迟500毫秒开始动画 duration: 1000,// 持续时间为1000毫秒 easing: 'ease-in-out',// 缓动函数为ease-in-out iterations: Infinity,// 迭代3次 direction: 'alternate',// 交替播放 endDelay: 1000,// 延迟1000毫秒开始动画 fill: "forwards",// 结束后保持最后一帧的效果 iterationStart: .2,// 从动画的20%位置开始迭代 composite: 'add',//使用add合成行为 keyframes: keyframes,//指定关键帧 playbackRate: 2.0,//播放速率为2倍 iterationComposite: 'accumulate',//使用accumulate合成行为 pseudoElement: '::after'//应用于after伪元素 } const keyframe = new KeyframeEffect(box, keyframes, options); function playHandler() { const animation = new Animation(keyframe, document.timeline); animation.play(); } </script> </body> </html>
效果
动画对象
全局Animation类
创建完成动画的关键帧后,我们可以使用全局的Animation类创建动画,动画的形式就是上面的关键帧
const box = document.querySelector(".box") const keyframes = [ { left: 0, top: "50px" }, { left: '100px', top: "100px" }, { top: "150px" } ]; const keyframe = new KeyframeEffect(box, keyframes, 1000); function playPauseHandler() { const animation = new Animation(keyframe); animation.play(); }
使用new Animation(keyframe)创建新的动画,然后使用play函数对动画进行激活
效果如下
Animation构造函数的参数有两个:关键帧对象AnimationEffect和时间线AnimationTimeline,前者就是上面说到的KeyframeEffect,AnimationTimeline一般可以使用document.timeline来描述
const animation = new Animation(keyframe, document.timeline);
animation对象中有许多属性和方法
属性
- id:返回动画的唯一标识符。
- startTime:动画开始的时间戳。
- currentTime:当前动画的时间,以毫秒为单位。
- playbackRate:动画的播放速率,默认值为1。
- effect:动画的效果,KeyframeEffect对象。
- timeline:动画所使用的时间轴,AnimationTimeline对象。
- playState:动画的当前播放状态,可能的值为 "idle"、"pending"、"running"、"paused"、"finished"。
- pending:动画的等待状态,即动画是否处于 pending 状态。
方法
- play(): 播放动画。
- pause(): 暂停动画。
- cancel(): 取消动画。
- finish(): 完成动画。
- reverse(): 反转动画的播放方向。
- updatePlaybackRate(playbackRate): 更新动画的播放速率。
- addEventListener(type, listener): 在动画上添加事件监听器。如:finish(完成)、cancel(取消)和pause(暂停)等
- removeEventListener(type, listener): 从动画上移除事件监听器。
- oncancel: 一个事件处理程序,当动画被取消时执行。
- onfinish: 一个事件处理程序,当动画完成时执行。
使用示例
<!DOCTYPE html> <html lang="CH"> <head> <meta charset="UTF-8" /> <title>webAnimationsAPI</title> <style> html, body { width: 100%; height: 100%; position: relative; } .box { width: 200px; height: 200px; top: 50px; position: absolute; background: lightblue; } </style> </head> <body> <div class="box"></div> <button onclick="playHandler()">开始</button> <button onclick="pauseHandler()">暂停</button> <button onclick="cancelHandler()">取消、重置</button> <button onclick="reverseHandler()">反向运行</button> <button onclick="finishHandler()">完成动画</button> <button onclick="playbackRateHandler()">更新动画速率</button> <button onclick="playStateHandler()">获取状态</button> <button onclick="currentTimeHandler()">获取时间轴位置</button> <script> const box = document.querySelector(".box") const keyframes = [ { left: 0 }, { left: '300px' }, ]; const keyframe = new KeyframeEffect(box, keyframes, { duration: 1000, iterations: Infinity, direction: 'alternate', fill: "forwards", }); const animation = new Animation(keyframe, document.timeline); animation.addEventListener("finish", console.info) animation.addEventListener("cancel", console.info) animation.addEventListener("remove", console.info) function playHandler() { animation.play(); } function pauseHandler() { animation.pause(); } function cancelHandler() { animation.cancel(); } function reverseHandler() { animation.reverse(); } function finishHandler() { animation.finish();// 当iterations等于infinity时无法触发完成 } function playStateHandler() { console.log(animation.playState); } function playbackRateHandler() { animation.updatePlaybackRate(2) } function currentTimeHandler() { console.log(animation.currentTime); } </script> </body> </html>
效果如下
标签中的animate函数
全局的Element标签对象继承于Animatable接口
该接口描述了两个方法:animate为当标签增加动画与getAnimations获取当前标签全部动画
interface Animatable { animate(keyframes: Keyframe[] | PropertyIndexedKeyframes | null, options?: number | KeyframeAnimationOptions): Animation; getAnimations(options?: GetAnimationsOptions): Animation[]; }
用法和KeyframeEffect+Animation类似
<!DOCTYPE html> <html lang="CH"> <head> <meta charset="UTF-8" /> <title>webAnimationsAPI</title> <style> html, body { width: 100%; height: 100%; position: relative; } .box { width: 200px; height: 200px; top: 50px; position: absolute; background: lightblue; } </style> </head> <body> <div class="box"></div> <button onclick="playHandler()">开始</button> <button onclick="pauseHandler()">暂停</button> <script> const box = document.querySelector(".box") const keyframes = [ { left: 0 }, { left: '300px' }, ]; const opts = { duration: 1000, iterations: Infinity, direction: 'alternate', fill: "forwards", } const animation = box.animate(keyframes, opts) function playHandler() { animation.play(); } function pauseHandler() { animation.pause(); } </script> </body> </html>
总结
本文与大家分享了16年新推出的JS原生动画WAAPI,使用这种方式创建的动画对象功能十分强大,其中我们可以使用KeyframeEffect设置标签关键帧的样式,通过Animation对象运行标签的动画。与前面的两篇关于动画的文章相比,WAAPI虽然强大,但是使用时还需要考虑兼容性问题。
好了,以上就是文章的全部内容了,希望文章内容对你有帮助,如果觉得文章不错的话,还望三连支持一下博主,谢谢~