最近搞了一个类似于红包雨的活动,研究了一下红包雨的实现方式。其中animationend 事件在 CSS 动画完成后触发,这个是我首次接触到的,所以就准备记录下来。
红包雨代码如下:
<template>
<div class="ser_home">
<ul class="red_packet" id="red_packet">
<template v-for="(item, index) in liParams">
<li
:style="{
left: item.left,
animationDuration: item.durTime,
webkitAnimationDuration: item.durTime,
}"
:class="item.cls"
:data-index="index"
@animationEnd="removeDom"
:key="index"
>
<a href="javascript:;">
<i
:style="{
transform: item.transforms,
webkitTransform: item.transforms,
}"
></i>
</a>
</li>
</template>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
liParams: [],
timer: null,
duration: 10000, // 定义时间 红包雨持续的时间
};
},
mounted() {
this.startRedPacket();
// 持续多长时间之后结束红包雨,清除这个方法,
setTimeout(() => {
// 多少时间结束
clearTimeout(this.timer);
console.log("结束定时器");
return;
}, this.duration);
},
methods: {
/**
* 开启动画
*/
startRedPacket() {
let win =
document.documentElement.clientWidth || document.body.clientWidth;
let left = parseInt(Math.random() * (win - 50) + 0);
let rotate = parseInt(Math.random() * (45 - -45) - 45) + "deg"; // 旋转角度
let scales = (Math.random() * (12 - 8 + 1) + 8) * 0.1; // 图片尺寸
let durTime = Math.random() * (2.5 - 1.2 + 1) + 1.2 + "s"; // 时间 1.2和1.2这个数值保持一样
console.log(durTime);
this.liParams.push({
left: left + "px",
cls: "move_1",
transforms: "rotate(" + rotate + ") scale(" + scales + ")",
durTime: durTime,
});
// 持续多长时间之后结束红包雨,清除这个方法,
// setTimeout(() => {
// // 多少时间结束
// clearTimeout(this.timer);
// console.log('结束定时器');
// return;
// }, this.duration);
// 每个100微秒去执行startRedPacket这个方法
this.timer = setTimeout(() => {
this.startRedPacket();
}, 100);
},
/**
* 回收dom节点
*/
removeDom(e) {
let target = e.currentTarget;
document.querySelector("#red_packet").removeChild(target);
},
},
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
.ser_home {
width: 100%;
height: 100%;
}
.red_packet {
display: block;
position: relative;
// overflow: hidden;
width: 100%;
height: 100%;
i {
width: 48px;
height: 69px;
display: block;
// background: url("../assets/repacked.png") no-repeat;
background: url("../assets/repacked.png");
background-size: 50px 50px;
background-repeat: no-repeat;
}
li {
position: absolute;
animation: all 3s linear;
top: -100px;
z-index: 10;
list-style: none;
// animation的具体使用可以自己百度一下
&.move_1 {
-webkit-animation: aim_move 5s linear 1 forwards;
animation: aim_move 5s linear 1 forwards;
}
}
a {
display: block;
}
}
@keyframes aim_move {
0% {
-webkit-transform: translateY(0);
transform: translateY(0);
}
// vh:1vh等于视口高度的1%。
// 视口单位中的“视口”,桌面端指的是浏览器的可视区域;移动端指的就是Viewport中的Layout Viewport,
// “视区”所指为浏览器内部的可视区域大小,即window.innerWidth/window.innerHeight大小,不包含任务栏标题栏以及底部工具栏的浏览器区域大小。。
100% {
-webkit-transform: translateY(120vh);
transform: translateY(120vh);
}
}
</style>
其中这段代码中的 @animationEnd=“removeDom” 是重点
<li
:style="{
left: item.left,
animationDuration: item.durTime,
webkitAnimationDuration: item.durTime,
}"
:class="item.cls"
:data-index="index"
@animationEnd="removeDom"
:key="index"
>
animationend 事件在 CSS 动画完成后触发
CSS 动画播放时,会发生以下三个事件:
- animationstart - CSS 动画开始后触发
- animationiteration - CSS 动画重复播放时触发
- animationend - CSS 动画完成后触发
在动画播放结束之后移除该元素,很好的一个思路。
而且其中关于css3中的动画属性animation和transform应用也值得借鉴。