如何在ASP.NET网页中手动控制Confetti(彩屑)效果的启停
彩屑效果启停功能修复方案
问题说明
现有彩屑代码存在以下问题:页面加载时自动运行效果,点击停止按钮会意外重启效果。需要实现:
- 页面加载时不启动彩屑效果
- 点击「Start」按钮启动彩屑
- 点击「Stop」按钮停止彩屑
关键问题分析
- 原代码直接调用
start()和stop(),导致页面加载自动执行效果 - ASP.NET服务器按钮默认触发页面回发,刷新后重新执行代码,造成停止按钮看似重启效果
- 原
stop()函数添加了5秒延迟,不符合即时停止需求
修正后的代码示例
HTML代码
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="Confetti.WebForm1" %> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Confetti</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Product Sans'; } html, body { width: 100%; height: 100%; background: #f1f1f1; display: flex; align-items: center; justify-content: center; flex-direction: column; gap: 2rem; } p { font-size: 4rem; text-shadow: 0 0 10px; } .button-group { display: flex; gap: 1rem; } button { padding: 0.8rem 2rem; font-size: 1.2rem; border: none; border-radius: 8px; cursor: pointer; background: #2196F3; color: white; transition: background 0.3s; } button:hover { background: #1976D2; } </style> <script src="Script.js"></script> </head> <body> <p>Confetti Effect 🎇</p> <div class="button-group"> <button id="btnStart_Confetti">Start</button> <button id="btnStop_Confetti">Stop</button> </div> <script> // 绑定按钮点击事件 document.getElementById('btnStart_Confetti').addEventListener('click', function() { confetti.start(); }); document.getElementById('btnStop_Confetti').addEventListener('click', function() { confetti.stop(); }); </script> </body> </html>
Script.js代码(无需修改)
var confetti = { maxCount: 150, // 设置最大彩屑数量 speed: 2, // 设置粒子动画速度 frameInterval: 15, // 彩屑动画帧间隔(毫秒) alpha: 1.0, // 彩屑透明度(0-1,1为完全不透明) gradient: false, // 是否使用渐变色彩 start: null, // 启动彩屑动画(可选参数:超时时间、最小/最大数量) stop: null, // 停止生成新彩屑 toggle: null, // 切换彩屑启停状态 pause: null, // 暂停彩屑动画 resume: null, // 恢复彩屑动画 togglePause: null, // 切换暂停状态 remove: null, // 立即停止并清除所有彩屑 isPaused: null, // 返回是否处于暂停状态 isRunning: null // 返回动画是否正在运行 }; (function () { confetti.start = startConfetti; confetti.stop = stopConfetti; confetti.toggle = toggleConfetti; confetti.pause = pauseConfetti; confetti.resume = resumeConfetti; confetti.togglePause = toggleConfettiPause; confetti.isPaused = isConfettiPaused; confetti.remove = removeConfetti; confetti.isRunning = isConfettiRunning; var supportsAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame; var colors = ["rgba(30,144,255,", "rgba(107,142,35,", "rgba(255,215,0,", "rgba(255,192,203,", "rgba(106,90,205,", "rgba(173,216,230,", "rgba(238,130,238,", "rgba(152,251,152,", "rgba(70,130,180,", "rgba(244,164,96,", "rgba(210,105,30,", "rgba(220,20,60,"]; var streamingConfetti = false; var animationTimer = null; var pause = false; var lastFrameTime = Date.now(); var particles = []; var waveAngle = 0; var context = null; function resetParticle(particle, width, height) { particle.color = colors[(Math.random() * colors.length) | 0] + (confetti.alpha + ")"); particle.color2 = colors[(Math.random() * colors.length) | 0] + (confetti.alpha + ")"); particle.x = Math.random() * width; particle.y = Math.random() * height - height; particle.diameter = Math.random() * 10 + 5; particle.tilt = Math.random() * 10 - 10; particle.tiltAngleIncrement = Math.random() * 0.07 + 0.05; particle.tiltAngle = Math.random() * Math.PI; return particle; } function toggleConfettiPause() { if (pause) resumeConfetti(); else pauseConfetti(); } function isConfettiPaused() { return pause; } function pauseConfetti() { pause = true; } function resumeConfetti() { pause = false; runAnimation(); } function runAnimation() { if (pause) return; else if (particles.length === 0) { context.clearRect(0, 0, window.innerWidth, window.innerHeight); animationTimer = null; } else { var now = Date.now(); var delta = now - lastFrameTime; if (!supportsAnimationFrame || delta > confetti.frameInterval) { context.clearRect(0, 0, window.innerWidth, window.innerHeight); updateParticles(); drawParticles(context); lastFrameTime = now - (delta % confetti.frameInterval); } animationTimer = requestAnimationFrame(runAnimation); } } function startConfetti(timeout, min, max) { var width = window.innerWidth; var height = window.innerHeight; window.requestAnimationFrame = (function () { return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (callback) { return window.setTimeout(callback, confetti.frameInterval); }; })(); var canvas = document.getElementById("confetti-canvas"); if (canvas === null) { canvas = document.createElement("canvas"); canvas.setAttribute("id", "confetti-canvas"); canvas.setAttribute("style", "display:block;z-index:999999;pointer-events:none;position:fixed;top:0"); document.body.prepend(canvas); canvas.width = width; canvas.height = height; window.addEventListener("resize", function () { canvas.width = window.innerWidth; canvas.height = window.innerHeight; }, true); context = canvas.getContext("2d"); } else if (context === null) context = canvas.getContext("2d"); var count = confetti.maxCount; if (min) { if (max) { if (min == max) count = particles.length + max; else { if (min > max) { var temp = min; min = max; max = temp; } count = particles.length + ((Math.random() * (max - min) + min) | 0); } } else count = particles.length + min; } else if (max) count = particles.length + max; while (particles.length < count) particles.push(resetParticle({}, width, height)); streamingConfetti = true; pause = false; runAnimation(); if (timeout) { window.setTimeout(stopConfetti, timeout); } } function stopConfetti() { streamingConfetti = false; } function removeConfetti() { stop(); pause = false; particles = []; } function toggleConfetti() { if (streamingConfetti) stopConfetti(); else startConfetti(); } function isConfettiRunning() { return streamingConfetti; } function drawParticles(context) { var particle; var x, y, x2, y2; for (var i = 0; i < particles.length; i++) { particle = particles[i]; context.beginPath(); context.lineWidth = particle.diameter; x2 = particle.x + particle.tilt; x = x2 + particle.diameter / 2; y2 = particle.y + particle.tilt + particle.diameter / 2; if (confetti.gradient) { var gradient = context.createLinearGradient(x, particle.y, x2, y2); gradient.addColorStop("0", particle.color); gradient.addColorStop("1.0", particle.color2); context.strokeStyle = gradient; } else context.strokeStyle = particle.color; context.moveTo(x, particle.y); context.lineTo(x2, y2); context.stroke(); } } function updateParticles() { var width = window.innerWidth; var height = window.innerHeight; var particle; waveAngle += 0.01; for (var i = 0; i < particles.length; i++) { particle = particles[i]; if (!streamingConfetti && particle.y < -15) particle.y = height + 100; else { particle.tiltAngle += particle.tiltAngleIncrement; particle.x += Math.sin(waveAngle) - 0.5; particle.y += (Math.cos(waveAngle) + particle.diameter + confetti.speed) * 0.5; particle.tilt = Math.sin(particle.tiltAngle) * 15; } if (particle.x > width + 20 || particle.x < -20 || particle.y > height) { if (streamingConfetti && particles.length <= confetti.maxCount) resetParticle(particle, width, height); else { particles.splice(i, 1); i--; } } } } })();
修改要点说明
- 移除原代码中自动执行的
start()和stop()调用,确保页面加载时无自动效果 - 替换ASP.NET服务器按钮为普通HTML按钮,避免页面回发导致的意外刷新
- 直接绑定按钮点击事件,调用原生
confetti.start()和confetti.stop(),去掉不必要的延迟 - 调整CSS布局,优化按钮与标题的排列效果
内容的提问来源于stack exchange,提问作者Yuppski
相关产品推荐
相关产品推荐

