vue3中实现红包雨!!前端实现红包雨页面。vue实现红包雨

最近作者遇到了一个红包雨的需求。就是 我们 平常 经常见到的 一堆红包从上往下开始落。然后用户们就哒哒哒哒哒的点😂

今天作者分享一个自己写的demo,个人认为还有很大的进步空间和改良的地方。如果大家有更好的方案,希望不吝赐教。🌹

OK  首先思考红包雨实现的几个关键点:

1. 从上往下落。这里作者用 css 的 animation 实现。

2. 红包的位置。因为我们需要让红包散点的铺开,之间有些距离。这样才能有更好的视觉效果。作者用 css 的定位。 父容器 用 relative,红包用 absolute。这样我们就 只用 调整 top 和 left 两个参数即可。

好,实操开始!!!启动!

首先作者是这么写的文件结构。

luckyBagRain ----红包雨

然后将红包封成了单独的组件,也就是 components 下的 luckyBag.vue

index.vue 是我们的父容器页面

utils 文件夹下的 creatLuckyBag.js 是创建红包的工具方法。因为作者想通过函数调用的方式调用组件,创建红包(使用vue 的 h 和 render 函数,类似于element-plus 的 message 组件)。而不是在父组件里面通过 v-for 去循环。

源码如下:

index.vue

<script setup>
import { ref, onMounted } from 'vue'
import { createLuckyBag } from './utils/createLuckyBag.js'

let timer

onMounted(() => {
   // 开始执行掉落红包
   startDown(10, 3000)
})

function startDown(count, duration = 3000) {
   // timer 用于之后删除定时器
   timer = setInterval(() => {
      for (let index = 0; index < count; index++) {
         createLuckyBag()
      }
   }, duration)
}

</script>

<template>

   <div class="luckyBagRain">

   </div>

</template>

<style lang="scss" scoped>
.luckyBagRain {
   position: relative;
   height: 100vh;
   box-sizing: border-box;
   background-color: rgba($color: #000000, $alpha: 0.8);
   overflow: hidden;
}
</style>

luckyBag.vue

<script setup>
import { ref, onMounted } from 'vue'

//销毁组件方法
const props = defineProps({
   onDestroy: Function
})

const visible = ref(true)
const speed = ref({})

onMounted(() => {
   // 随机数 生成红包 top 和 left 的值。
   let x = Math.random() * window.innerWidth
   let y = Math.random() * 1000 * Math.random()
   // 随机时间,控制红包不同的下落速度
   let duration = Math.random() * 5 + 8
   //如果红包超出边框,则调整
   x = x > window.innerWidth * 0.8 ? x - window.innerWidth / 5 : x
   speed.value = {
      'animation-duration': duration + 's',
      'left': x + 'px',
      'top': y + 'px'
   }
   // 比动画结束前 1s 销毁组件
   setTimeout(() => {
      fade()
   }, (duration - 1) * 1000)
})

//点击之后配合transition 组件实现fade淡出效果,并销毁组件,后续和后端的交互也可在此处
function fade() {
   visible.value = false
   setTimeout(() => {
      props.onDestroy()
   }, 1000)
}

</script>

<template>

   <transition name="fade">
      <div :style="speed" @click="fade" v-if="visible" class="lucky-bag"></div>
   </transition>


</template>

<style lang="scss" scoped>
.lucky-bag {
   position: absolute;
   width: 60px;
   height: 80px;
   background: url("@/assets/img/activity/luckyBag.png") no-repeat;
   background-size: 100% 100%;
   animation: move linear;
}

.fade-enter-active,
.fade-leave-active {
   transition: all 0.4s ease;
}

.fade-enter-from,
.fade-leave-to {
   opacity: 0;
}

@keyframes move {
   0% {
      transform: translateY(-1000px);
   }

   100% {
      transform: translateY(100vh);
   }
}
</style>

creatLuckyBag.js

import { createVNode, render } from 'vue';
import LuckyBag from '../components/luckyBag.vue';
function createLuckyBag() {
    const container = document.createElement('div');
    const targetDom = document.getElementsByClassName('luckyBagRain')[0];

    const vm = createVNode(LuckyBag, {})
    vm.props.onDestroy = () => {
        render(null, container)
    }

    render(vm, container);
    targetDom.appendChild(container.firstElementChild);
}

export { createLuckyBag }

效果展示:

如果你在实现过程中遇到了任何问题,或者对本文有任何建议,欢迎在评论区留言交流。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值