当前位置:首页 > 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 实现文字播放栏(跑马灯效果) 方法一:使用 CSS 动画 + Vue 数据绑定 通过 CSS 的 @keyframes 实现动画效果,结合 Vue 的动态数据绑定控制内容。 <t…

vue实现按卡片轮播

vue实现按卡片轮播

实现卡片轮播的基本思路 在Vue中实现卡片轮播可以通过结合v-for指令和动态样式绑定完成。核心是维护一个当前显示卡片的索引,通过CSS过渡效果实现平滑切换。 基础实现步骤 模板部分 使用v-for…

vue实现弹窗可切换

vue实现弹窗可切换

实现弹窗可切换的 Vue 方案 动态组件切换 通过 Vue 的 <component :is="currentComponent"> 动态加载不同弹窗组件,结合 v-if 控制显示状态。…

vue 实现在线预览

vue 实现在线预览

Vue 实现在线预览的常见方法 使用 iframe 嵌入 通过 iframe 标签可以嵌入多种类型的文件,如 PDF、图片、网页等。需要确保文件地址可访问。 <template>…

vue实现继承语法糖

vue实现继承语法糖

在Vue中实现继承可以通过多种方式模拟类继承的效果,以下是常见的几种方法: 使用mixins实现逻辑复用 通过Vue的mixins机制共享组件选项,达到类似继承的效果: const Bas…

vue实现一个系统

vue实现一个系统

Vue 系统实现步骤 项目初始化与配置 使用 Vue CLI 或 Vite 创建项目: npm init vue@latest my-system 选择需要的配置(Router、Pinia 等)。…