当前位置:首页 > VUE

vue实现点击红包雨

2026-01-12 01:56:03VUE

Vue 实现点击红包雨效果

实现红包雨效果需要结合 Vue 的响应式数据绑定和动画效果。以下是具体实现方法:

创建红包组件

定义一个红包组件,包含红包图片和点击事件处理逻辑。可以使用 v-for 动态生成多个红包。

<template>
  <div 
    class="red-packet" 
    v-for="(packet, index) in packets" 
    :key="index"
    :style="{
      left: packet.left + 'px',
      top: packet.top + 'px',
      animation: `fall ${packet.duration}s linear infinite`
    }"
    @click="collectPacket(index)"
  >
    <img src="@/assets/red-packet.png" alt="红包">
  </div>
</template>

<script>
export default {
  data() {
    return {
      packets: []
    }
  },
  methods: {
    collectPacket(index) {
      this.packets.splice(index, 1)
      // 处理收集红包逻辑
    }
  }
}
</script>

添加红包雨动画

使用 CSS 动画实现红包下落效果。定义 fall 动画让红包从顶部移动到底部。

vue实现点击红包雨

.red-packet {
  position: absolute;
  width: 50px;
  height: 60px;
  cursor: pointer;
  z-index: 100;
}

@keyframes fall {
  from {
    transform: translateY(-100px);
  }
  to {
    transform: translateY(100vh);
  }
}

控制红包生成

在 Vue 组件中设置定时器,定期生成新的红包并随机设置位置和下落速度。

export default {
  mounted() {
    this.startRain()
  },
  methods: {
    startRain() {
      setInterval(() => {
        if (this.packets.length < 20) { // 控制最大红包数量
          this.packets.push({
            left: Math.random() * window.innerWidth,
            top: -60,
            duration: 3 + Math.random() * 5 // 随机下落速度
          })
        }
      }, 300) // 每300毫秒生成一个红包
    }
  }
}

优化性能

对于大量红包元素,可以使用 Vue 的 v-show 替代 v-if 减少 DOM 操作,或者使用虚拟滚动技术优化性能。

vue实现点击红包雨

<template>
  <div 
    class="red-packet" 
    v-for="(packet, index) in packets" 
    :key="index"
    v-show="packet.visible"
  >
    <!-- 红包内容 -->
  </div>
</template>

添加点击效果

为增强用户体验,可以在点击红包时添加动画效果或音效。

methods: {
  collectPacket(index) {
    this.packets[index].visible = false
    // 播放收集音效
    const audio = new Audio('collect-sound.mp3')
    audio.play()
    // 显示收集动画
    this.showCollectionEffect(this.packets[index])
  }
}

响应式调整

监听窗口大小变化,调整红包位置和动画参数。

mounted() {
  window.addEventListener('resize', this.adjustPackets)
},
beforeDestroy() {
  window.removeEventListener('resize', this.adjustPackets)
},
methods: {
  adjustPackets() {
    this.packets = this.packets.map(packet => ({
      ...packet,
      left: Math.random() * window.innerWidth
    }))
  }
}

完整示例

<template>
  <div class="red-packet-container">
    <div 
      class="red-packet" 
      v-for="(packet, index) in packets" 
      :key="index"
      :style="packetStyle(packet)"
      @click="collectPacket(index)"
    >
      <img src="@/assets/red-packet.png" alt="红包">
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      packets: [],
      maxPackets: 20
    }
  },
  mounted() {
    this.startRain()
    window.addEventListener('resize', this.adjustPackets)
  },
  beforeDestroy() {
    clearInterval(this.rainInterval)
    window.removeEventListener('resize', this.adjustPackets)
  },
  methods: {
    packetStyle(packet) {
      return {
        left: packet.left + 'px',
        top: packet.top + 'px',
        animation: `fall ${packet.duration}s linear infinite`,
        opacity: packet.visible ? 1 : 0
      }
    },
    startRain() {
      this.rainInterval = setInterval(() => {
        if (this.packets.length < this.maxPackets) {
          this.packets.push({
            left: Math.random() * window.innerWidth,
            top: -60,
            duration: 3 + Math.random() * 5,
            visible: true
          })
        }
      }, 300)
    },
    collectPacket(index) {
      this.packets[index].visible = false
      setTimeout(() => {
        this.packets.splice(index, 1)
      }, 500)
    },
    adjustPackets() {
      this.packets = this.packets.map(packet => ({
        ...packet,
        left: Math.min(packet.left, window.innerWidth - 50)
      }))
    }
  }
}
</script>

<style>
.red-packet-container {
  position: relative;
  width: 100%;
  height: 100vh;
  overflow: hidden;
}

.red-packet {
  position: absolute;
  width: 50px;
  height: 60px;
  cursor: pointer;
  z-index: 100;
  transition: opacity 0.3s;
}

@keyframes fall {
  from {
    transform: translateY(-100px);
  }
  to {
    transform: translateY(100vh);
  }
}
</style>

标签: 红包vue
分享给朋友:

相关文章

vue为啥能实现监听

vue为啥能实现监听

Vue 实现监听的原理 Vue 的监听能力主要基于其响应式系统,该系统通过数据劫持和依赖收集实现。当数据变化时,系统能自动触发视图更新或执行回调函数。 核心机制:Object.definePrope…

vue查看更多怎么实现

vue查看更多怎么实现

实现 Vue 的“查看更多”功能 数据截取与显示控制 通过 v-if 或 v-show 控制内容的显示与隐藏。初始状态下只显示部分内容,点击“查看更多”后展开完整内容。 <template&g…

vue实现导航栏切图

vue实现导航栏切图

Vue 实现导航栏切图 使用 Vue Router 实现基础导航 在 Vue 项目中,可以通过 Vue Router 实现导航栏的路由切换。创建一个导航栏组件,并在其中使用 <router-li…

vue实现点击旋转轮盘

vue实现点击旋转轮盘

实现点击旋转轮盘效果 在Vue中实现点击旋转轮盘效果,可以通过CSS动画和Vue的数据绑定结合完成。以下是一个完整的实现方案: 准备工作 需要安装Vue.js环境,可以通过CDN引入或使用Vue…

vue前端实现下载进度

vue前端实现下载进度

实现下载进度条的基本思路 在Vue中实现下载进度条,通常需要结合XMLHttpRequest或Fetch API来监听下载进度事件。通过计算已下载数据与总数据的比例,动态更新进度条的显示。 使用XM…

vue实现菜单栏锚点

vue实现菜单栏锚点

实现锚点菜单的基本思路 在Vue中实现菜单栏锚点功能,主要涉及两个方面:创建可跳转的锚点位置,以及菜单项的点击滚动控制。通过监听滚动事件可以高亮当前可见区域的对应菜单项。 创建页面锚点位置 在需要…