You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在ASP.NET网页中手动控制Confetti(彩屑)效果的启停

彩屑效果启停功能修复方案

问题说明

现有彩屑代码存在以下问题:页面加载时自动运行效果,点击停止按钮会意外重启效果。需要实现:

  • 页面加载时不启动彩屑效果
  • 点击「Start」按钮启动彩屑
  • 点击「Stop」按钮停止彩屑

关键问题分析

  1. 原代码直接调用start()和stop(),导致页面加载自动执行效果
  2. ASP.NET服务器按钮默认触发页面回发,刷新后重新执行代码,造成停止按钮看似重启效果
  3. 原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--;
                }
            }
        }
    }
})();

修改要点说明

  1. 移除原代码中自动执行的start()和stop()调用,确保页面加载时无自动效果
  2. 替换ASP.NET服务器按钮为普通HTML按钮,避免页面回发导致的意外刷新
  3. 直接绑定按钮点击事件,调用原生confetti.start()和confetti.stop(),去掉不必要的延迟
  4. 调整CSS布局,优化按钮与标题的排列效果

内容的提问来源于stack exchange,提问作者Yuppski

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.02 05:09:50