新年烟花祝福

7 阅读1分钟
2026新年快乐 * { margin: 0; padding: 0; box-sizing: border-box; } html, body { width: 100%; height: 100%; overflow: hidden; background: #000814; touch-action: none; font-family: "PingFang SC", "Microsoft YaHei", sans-serif; } canvas { position: fixed; top: 0; left: 0; width: 100%; height: 100%; display: block; } .wish-text { position: fixed; top: 35%; left: 50%; transform: translate(-50%, -50%); color: #fff; text-align: center; z-index: 10; pointer-events: none; width: 90%; } .main-title { font-size: 2.2rem; font-weight: bold; margin-bottom: 1rem; text-shadow: 0 0 10px #ffd700, 0 0 20px #ff6b6b; animation: glow 2s ease-in-out infinite alternate; } .sub-title { font-size: 1.2rem; line-height: 1.6; opacity: 0.95; text-shadow: 0 0 8px #4cc9f0; } @keyframes glow { from { filter: brightness(1); } to { filter: brightness(1.3); } } .tip { position: fixed; bottom: 15%; left: 50%; transform: translateX(-50%); color: rgba(255,255,255,0.6); font-size: 0.9rem; z-index: 10; pointer-events: none; animation: fade 3s ease-in-out infinite; } @keyframes fade { 0%,100% { opacity: 0.4; } 50% { opacity: 0.8; } }
2026 新年快乐
丙午马年 平安喜乐
万事顺意 岁岁年年
点击屏幕 绽放专属烟花
<script>
    const canvas = document.getElementById('fireworks');
    const ctx = canvas.getContext('2d');
    let width = window.innerWidth;
    let height = window.innerHeight;
    let particles = [];
    let fireworks = [];
    let hue = 0;

    // 适配屏幕尺寸
    function resizeCanvas() {
        width = window.innerWidth;
        height = window.innerHeight;
        canvas.width = width;
        canvas.height = height;
    }
    resizeCanvas();
    window.addEventListener('resize', resizeCanvas);

    // 随机数工具
    function random(min, max) {
        return Math.random() * (max - min) + min;
    }

    // 烟花主体类
    class Firework {
        constructor(sx, sy, tx, ty) {
            this.x = sx;
            this.y = sy;
            this.sx = sx;
            this.sy = sy;
            this.tx = tx;
            this.ty = ty;
            this.distanceToTarget = Math.hypot(tx - sx, ty - sy);
            this.distanceTraveled = 0;
            this.coordinates = [];
            this.coordinateCount = 3;
            while(this.coordinateCount--) {
                this.coordinates.push([this.x, this.y]);
            }
            this.angle = Math.atan2(ty - sy, tx - sx);
            this.speed = 2;
            this.acceleration = 1.05;
            this.brightness = random(50, 70);
            this.targetRadius = 1;
        }

        update(index) {
            this.coordinates.pop();
            this.coordinates.unshift([this.x, this.y]);
            if(this.targetRadius < 8) {
                this.targetRadius += 0.3;
            } else {
                this.targetRadius = 1;
            }
            this.speed *= this.acceleration;
            const vx = Math.cos(this.angle) * this.speed;
            const vy = Math.sin(this.angle) * this.speed;
            this.distanceTraveled = Math.hypot(this.x - this.sx, this.y - this.sy);
            if(this.distanceTraveled >= this.distanceToTarget) {
                createParticles(this.tx, this.ty);
                fireworks.splice(index, 1);
            } else {
                this.x += vx;
                this.y += vy;
            }
        }

        draw() {
            ctx.beginPath();
            ctx.moveTo(this.coordinates[this.coordinates.length - 1][0], this.coordinates[this.coordinates.length - 1][1]);
            ctx.lineTo(this.x, this.y);
            ctx.strokeStyle = `hsl(${hue}, 100%, ${this.brightness}%)`;
            ctx.lineWidth = 2;
            ctx.stroke();

            ctx.beginPath();
            ctx.arc(this.tx, this.ty, this.targetRadius, 0, Math.PI * 2);
            ctx.stroke();
        }
    }

    // 烟花爆炸粒子类
    class Particle {
        constructor(x, y) {
            this.x = x;
            this.y = y;
            this.coordinates = [];
            this.coordinateCount = 5;
            while(this.coordinateCount--) {
                this.coordinates.push([this.x, this.y]);
            }
            this.angle = random(0, Math.PI * 2);
            this.speed = random(1, 10);
            this.friction = 0.95;
            this.gravity = 1;
            this.hue = random(hue - 20, hue + 20);
            this.brightness = random(50, 80);
            this.alpha = 1;
            this.decay = random(0.015, 0.03);
        }

        update(index) {
            this.coordinates.pop();
            this.coordinates.unshift([this.x, this.y]);
            this.speed *= this.friction;
            this.x += Math.cos(this.angle) * this.speed;
            this.y += Math.sin(this.angle) * this.speed + this.gravity;
            this.alpha -= this.decay;
            if(this.alpha <= this.decay) {
                particles.splice(index, 1);
            }
        }

        draw() {
            ctx.beginPath();
            ctx.moveTo(this.coordinates[this.coordinates.length - 1][0], this.coordinates[this.coordinates.length - 1][1]);
            ctx.lineTo(this.x, this.y);
            ctx.strokeStyle = `hsla(${this.hue}, 100%, ${this.brightness}%, ${this.alpha})`;
            ctx.lineWidth = 2;
            ctx.stroke();
        }
    }

    // 生成爆炸粒子群
    function createParticles(x, y) {
        let particleCount = 100;
        while(particleCount--) {
            particles.push(new Particle(x, y));
        }
    }

    // 自动循环发射烟花
    function autoFirework() {
        if(fireworks.length < 5) {
            fireworks.push(new Firework(
                width / 2,
                height,
                random(0, width),
                random(0, height * 0.7)
            ));
        }
    }

    // 动画主循环
    function animate() {
        requestAnimationFrame(animate);
        hue += 0.5;
        ctx.globalCompositeOperation = 'destination-out';
        ctx.fillStyle = 'rgba(0, 0, 0, 0.1)';
        ctx.fillRect(0, 0, width, height);
        ctx.globalCompositeOperation = 'lighter';

        let i = fireworks.length;
        while(i--) {
            fireworks[i].draw();
            fireworks[i].update(i);
        }

        i = particles.length;
        while(i--) {
            particles[i].draw();
            particles[i].update(i);
        }
    }

    // 点击/触摸屏幕发射烟花
    function launchFirework(x, y) {
        fireworks.push(new Firework(width / 2, height, x, y));
    }

    canvas.addEventListener('click', (e) => {
        launchFirework(e.clientX, e.clientY);
    });

    canvas.addEventListener('touchstart', (e) => {
        e.preventDefault();
        const touch = e.touches[0];
        launchFirework(touch.clientX, touch.clientY);
    }, { passive: false });

    // 启动动画
    animate();
    setInterval(autoFirework, 800);
</script>