HTML核心代码:
<ul class="red_packet" id="red_packet">
<li
v-for="(item, index) in liParams"
:key="index"
:style="{
left: item.left,
animationDuration: item.durTime,
}"
class="move_1"
:data-index="index"
@webkitAnimationEnd="removeDom" //没点击的红包到底部消除节点
:class="{ active: selectedItems.includes(item.activeId) }" //点击红包后消失
@click.prevent="onClick(item.activeId)"
>
<span>
<i
:style="{
transform: item.transforms,
'background-image':
'url(' +
(activeItems.includes(item.activeId) //点击前红包的图片和点击后红包的图片
? prizeInfo.redPacketImageClick
: prizeInfo.redPacketImageNoClick) +
')',
}"
></i>
</span>
</li>
</ul>
TS代码:
export default class RedEnvelopeRain extends Mixins(Mixin){
liParams: Array<{
left?: string;
cls?: string;
transforms?: string;
durTime?: string;
activeId: number;
}> = []; //红包item数组
timer = 0; //红包下落
duration = 0; // 游戏时间
countdown = 5; //倒计时5秒
priczeNum = 0; //点击红包的个数
selectedItems: Array<number> = []; //点击红包消失id数组
activeItems: Array<number> = []; //点击红包切换图片的数组
itemId = 0; //初始红包下标0开始计算
prizeInfo: cms.ActivityInfoDto = { menuType: "" }; //接口返回信息
mounted(): void {
this.startRedPacket();
}
/**
* 开启动画
*/
startRedPacket(): void {
let win = document.documentElement.clientWidth || document.body.clientWidth;
let left = Math.random() * (win - 50) + 0;
let rotate = 0; // 旋转角度
let scales = (Math.random() * (12 - 8 + 1) + 8) * 0.1; // 图片尺寸
let durTime = Math.random() * (2.5 - 1.2 + 1) + 2 + "s"; // 时间 1.2和1.2这个数值保持 一样
this.itemId++;
this.liParams.push({
left: left + "px",
cls: "move_1",
transforms: "rotate(" + rotate + ") scale(" + scales + ")",
durTime: durTime,
activeId: this.itemId,
});
let onceTime =
this.duration /
(this.prizeInfo.redPacketNum // 游戏总时间(接口返回)/ 红包数量
? this.prizeInfo.redPacketNum
: this.duration);
this.timer = Number(
setTimeout(() => {
this.startRedPacket();
}, onceTime) //多少时间执行一次
);
}
/*
* 点击红包
*/
onClick(id: number): void {
if (this.selectedItems.includes(id) || this.activeItems.includes(id)) {
//如果当前红包已点击红包就禁止连续点击
return;
}
this.priczeNum++;
this.activeItems.push(id);
let timer = setTimeout(() => {
//设置定时器当红包展示打开过程后才消失。
this.selectedItems.push(id);
clearTimeout(timer);
}, 200);
}
/**
* 回收dom节点
*/
removeDom(e: { currentTarget: Element }): void {
let target = e.currentTarget;
if (target) {
(document.querySelector("#red_packet") as Element).removeChild(target);
}
return;
}
}
css样式:
.red_packet {
display: block;
position: relative;
overflow: hidden;
width: 100%;
height: 100%;
i {
width: 1.1rem;
height: 1.2rem;
display: block;
background-repeat: no-repeat;
background-size: cover;
}
li {
position: absolute;
animation: all 3s linear;
top: -100px;
z-index: 10;
&.move_1 {
-webkit-animation: aim_move 5s linear 1 forwards;
animation: aim_move 5s linear 1 forwards;
}
}
a {
display: block;
}
}
.active {
display: none;
}
@keyframes aim_move {
0% {
-webkit-transform: translateY(0);
transform: translateY(0);
}
100% {
-webkit-transform: translateY(120vh);
transform: translateY(120vh);
}
}