如何将指定JS特效代码转换为Vue代码并正确实现frame方法
完整实现代码
Template 部分修改
<template> <section id="successful-order" class="container"> <!-- 新增canvas用于绘制彩屑效果 --> <canvas id="confetti-canvas" style="position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; pointer-events: none; z-index: 999;"></canvas> <div class="row office-banner"> <div class="col-12"> <img :src="successful" alt="Popper Image"/> <div class="sub-title">Your order is complete!</div> <div>You will be receiving a confirmation email with your order details.</div> <div class="button-area"> <button class="btn button">Checkout your tickets</button> <button class="btn button-secondary">Go to homepage!</button> </div> </div> </div> </section> </template>
Script 部分修改
<script> import successful from "../../../../img/poppers.png"; export default { data() { return { successful: successful, // 可自行扩展更多彩屑颜色 color: ["#8b5642", "#6a696b", "#f2c029", "#e85d44", "#58b9c7"], particles: [], // 存储所有彩屑实例 animationId: null, // 存储动画帧ID用于销毁 ctx: null, // canvas 上下文 canvasWidth: 0, canvasHeight: 0 }; }, mounted() { // 初始化canvas const canvas = document.getElementById('confetti-canvas') this.ctx = canvas.getContext('2d') this.canvasWidth = canvas.width = window.innerWidth this.canvasHeight = canvas.height = window.innerHeight // 监听窗口大小变化调整canvas尺寸 window.addEventListener('resize', this.resizeCanvas) // 初始化彩屑 this.initParticles() // 启动动画 this.frame() }, beforeUnmount() { // 组件销毁前清除动画和事件监听,避免内存泄漏 window.removeEventListener('resize', this.resizeCanvas) if (this.animationId) cancelAnimationFrame(this.animationId) }, methods: { resizeCanvas() { const canvas = document.getElementById('confetti-canvas') this.canvasWidth = canvas.width = window.innerWidth this.canvasHeight = canvas.height = window.innerHeight }, initParticles() { // 生成200个彩屑,数量可自行调整 for (let i = 0; i < 200; i++) { this.particles.push({ x: Math.random() * this.canvasWidth, // 随机x轴起始位置 y: Math.random() * -this.canvasHeight, // 从屏幕上方外开始下落 r: Math.random() * 6 + 2, // 彩屑大小 d: Math.random() * 50 + 10, // 下落速度系数 color: this.color[Math.floor(Math.random() * this.color.length)], // 随机颜色 tilt: Math.random() * 10 - 10, // 倾斜角度 tiltAngleIncrement: Math.random() * 0.07 + 0.05, // 倾斜角度变化速度 tiltAngle: 0 }) } }, frame() { this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight) let allOutOfScreen = true this.particles.forEach((p, i) => { // 更新倾斜角度 p.tiltAngle += p.tiltAngleIncrement p.y += (Math.cos(p.d) + 3 + p.r / 2) / 2 p.x += Math.sin(p.tiltAngle) p.tilt = Math.sin(p.tiltAngle - i / 3) * 15 // 只要还有粒子在屏幕内就继续动画 if (p.y < this.canvasHeight) allOutOfScreen = false // 绘制彩屑 this.ctx.fillStyle = p.color this.ctx.beginPath() this.ctx.arc(p.x, p.y, p.r, 0, 2 * Math.PI) this.ctx.fill() }) // 所有粒子都掉出屏幕就停止动画 if (allOutOfScreen) { cancelAnimationFrame(this.animationId) return } this.animationId = requestAnimationFrame(this.frame) } } }; </script>
核心修改说明
- 新增canvas元素作为彩屑绘制载体,设置固定定位、最高层级且不响应鼠标事件,不会影响原有页面交互
- 在mounted生命周期钩子中初始化canvas尺寸、彩屑数据并启动动画,此时组件已经挂载到DOM上可以正常获取canvas元素
- 在beforeUnmount钩子中清除动画帧和事件监听,避免内存泄漏
- frame方法中每一帧先清空画布,再更新所有彩屑的位置、倾斜属性后重新绘制,实现流畅的下落动画效果
- 可以自行调整
initParticles方法中的彩屑数量、颜色数组、速度参数来匹配你想要的视觉效果
内容的提问来源于stack exchange,提问作者magic bean
相关产品推荐
相关产品推荐

