当前位置:首页 > 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 动画让红包从顶部移动到底部。

.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 操作,或者使用虚拟滚动技术优化性能。

<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])
  }
}

响应式调整

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

vue实现点击红包雨

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 中实现换行可以通过多种方式,具体取决于使用场景和需求。以下是常见的几种方法: 使用 HTML 的 <br> 标签 在模板中直接使用 <br…

vue 动画实现

vue 动画实现

Vue 动画实现方式 Vue 提供了多种方式实现动画效果,主要分为内置组件和第三方库集成。 使用 Vue 内置过渡组件 Vue 的 <transition> 和 <transiti…

vue mvvm 实现

vue mvvm 实现

Vue MVVM 实现原理 Vue.js 的 MVVM(Model-View-ViewModel)架构通过数据绑定和响应式系统实现视图与数据的自动同步。以下是其核心实现机制: 数据劫持与响应式系统…

vue实现导航

vue实现导航

使用 Vue Router 实现导航 Vue Router 是 Vue.js 官方提供的路由管理器,用于构建单页应用(SPA)的导航系统。以下是实现导航的基本步骤。 安装 Vue Router n…

vue下载实现

vue下载实现

Vue 下载实现方法 在 Vue 项目中实现文件下载功能可以通过多种方式完成,以下是几种常见的方法: 使用 <a> 标签实现下载 通过动态创建 <a> 标签并设置 href…

vue框架实现CRM

vue框架实现CRM

Vue框架实现CRM系统 使用Vue框架构建CRM(客户关系管理)系统需要结合前端技术栈和后端API。以下为关键实现方法: 技术选型 核心框架:Vue 3(Composition API)…