请马上登录,朋友们都在花潮里等着你哦:)
您需要 登录 才可以下载或查看,没有账号?立即注册
x
如下效果是纯CSS关键帧动画,请特别注意,未经干预前动画由CSS直接驱动,三朵花的旋转无限循环:
点击接力旋转按钮,其中一朵花朵继续旋转,另外两朵花暂停,旋转着的花朵停下,下一朵花紧接着旋转,如此循环往复。点击恢复原状按钮,结束接力赛旋转,三朵花的旋转状态恢复到初始时的样子。
接力运行动画的实现得益于 getAnimations() 方法,该方法由 Web Animations API(简称WAAPI) 提供,我们之前介绍的原生 JS animate() 方法也是由 WAAPI 提供。
getAnimations() 方法可以基于 document 即 DOM,document.getAnimations();,这将拿到整个页面的所有动画,包含三种类型的动画:① CSS动画(CSS Animations),② CSS过度动画(CSS Transitions),③ Web动画(Web Animations,即之前介绍的原生JS Animate动画),数据以数组形式存储;也可以基于 element 即某个或某些特定的HTML元素,拿到的也是数组数据。利用这些数据,我们可以相应地管理各类WAAPI所能管理的动画,本文重点讨论的动画类型是CSS动画——如前已述,接力旋转按钮点击后的效果就是通过基于 document 的 getAnimations() 方法实现的。
考虑一下下面的CSS样式表:
<style>
.pic { position: absolute; left: 20px; top: 20px; animation: rot 4s linear infinite; }
@keyframes rot {
to { transform: rotate(360deg); }
}
</style>
留意第2行代码,简写形式的 animation 属性中有一个参数 infinite,它是 animation-iteration-count 的值,指动画运行次数,infinite 是无限循环运行。无限循环运行的动画 onfinish 事件(动画完成事件)永远不会被触发,因此需要动态修改动画运行次数,比如改为运行一次。控制CSS关键帧动画可以通过修改元素级CSS样式来处理,我们会拿到要控制动画的所有元素,在JS中这么处理就可以达到目的:
element.style.animationIterationCount = 1;
当然,如果CSS样式表中直接在简写属性的 animation 值中去掉 infinite,那一切将很简单,我们只需简单地通过 getAnimations() 方法获取所有的动画然后控制这些动画就好。或者,不在CSS样式表中修改动画运行次数,那能否通过拿到的动画操作句柄,使用 WAAPI 的方式去修改动画运行次数呢?针对CSS动画目前不行,动画对象.iterations = 1; 这样的设置目前仅能作用于由 JS 的 animate() 方法生成的动画。
修改动画运行次数为1次之后,接着就可以真奔主题,让CSS关键帧动画接力运行。我们要做的仅仅是封装 动画对象.onfinish 事件:让前一个动画运行结束时开启下一个动画的运行,并且令其头尾衔接。以下是完整的实现代码,其运行结果是动画一开始就进入接力状态,且每一朵花都具备接受点击功能,通过点击任意一朵花,动画都会在播放、暂停两种状态间切换:
<style>
.tz { margin: 20px auto; width: 760px; height: 400px; border: 1px solid gray; position: relative; }
.pic { position: absolute; left: 20px; top: 20px; animation: rot 4s linear infinite; }
.pic:nth-of-type(1) { left: 120px; top: 30px; }
.pic:nth-of-type(2) { left: 460px; top: 10px; }
.pic:nth-of-type(3) { left: 320px; top: 200px; }
@keyframes rot {
to { transform: rotate(360deg); }
}
</style>
<div id="tz">
<img class="pic" alt="" src="https://638183.freep.cn/638183/t23/btn/12f.png" />
<img class="pic" alt="" src="https://638183.freep.cn/638183/t23/btn/12f.png" />
<img class="pic" alt="" src="https://638183.freep.cn/638183/t23/btn/12f.png" />
</div>
<script>
const pics = document.querySelectorAll('.pic'); //所有运行动画的元素
const anis = document.getAnimations(); //所有动画对象
var isplaying = true, current = 0; //播放状态、当前播放的动画索引
//遍历动画对象
anis.forEach((ani,key) => {
pics[key].style.animationIterationCount = 1; //改变元素的动画运行次数
if(key > 0) ani.pause(); //除了第一个动画,都先暂停
//如果不是最后一个动画对象,它运行结束时
if(key < anis.length - 1) ani.onfinish = () => {
anis[key+1].play(); //启动下一个动画
current = key + 1; //当前动画索引加 1
}
//否则如果是最后一个动画,它运行结束时
else ani.onfinish = () => {
anis[0].play(); //启动第一个动画
current = 0; //当前动画索引是 0
}
});
//花朵点击事件
pics.forEach((pic, key) => pic.onclick = () => {
//如果动画正在运行,则令当前运行的动画对象暂停,反之,如果动画暂停中,则令当前动画对象播放
isplaying ? anis[current].pause() : anis[current].play();
isplaying = !isplaying; //布尔变量值取反
});
</script>
以上代码可以复制到 pencil code 或存为本地HTML文档运行以查看运行效果及进行相关研究。
|