当前位置: 首页 > ai >正文

放爱心烟花

<!DOCTYPE html>
<html>
<head>
    <title>心形烟花特效</title>
    <style>
        body { margin: 0; overflow: hidden; background: #000; }
        #modeBtn {
            position: fixed; top: 20px; left: 20px;
            padding: 10px; background: rgba(255,255,255,0.2);
            color: white; border: none; cursor: pointer;
        }
    </style>
</head>
<body>
    <button id="modeBtn">自动模式</button>
    <canvas id="canvas"></canvas>

<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
let isAutoMode = false;
const modeBtn = document.getElementById('modeBtn');

// 心形生成算法优化(增强粒子密度与尺寸)
function generateHeartPoints(centerX, centerY) {
    const points = [];
    for(let t=0; t < Math.PI*2; t += 0.03) { // 增加采样密度
        const x = 16 * Math.pow(Math.sin(t),3);
        const y = -13*Math.cos(t) + 5*Math.cos(2*t) + 2*Math.cos(3*t) + Math.cos(4*t);
        points.push({
            x: centerX + x*12,  // 放大系数提升至12
            y: centerY + y*12,
            size: Math.random()*4 + 2, // 粒子尺寸增大
            hue: Math.random()*360
        });
    }
    return points;
}

// 粒子类(增加运动阻尼与颜色动态)
class Particle {
    constructor(x, y, target) {
        this.x = x;
        this.y = y;
        this.target = target;
        this.speed = { x: 0, y: 0 };
        this.alpha = 1;
        this.friction = 0.93; // 增加运动阻尼
    }

    update() {
        // 向心形目标点加速
        const dx = this.target.x - this.x;
        const dy = this.target.y - this.y;
        this.speed.x += dx * 0.02;
        this.speed.y += dy * 0.02;
        
        // 物理模拟
        this.x += this.speed.x;
        this.y += this.speed.y;
        this.speed.x *= this.friction;
        this.speed.y *= this.friction;
        this.alpha -= 0.006; // 延长显示时间
    }

    draw() {
        ctx.beginPath();
        ctx.arc(this.x, this.y, this.target.size, 0, Math.PI*2);
        ctx.fillStyle = `hsla(${this.target.hue},100%,60%,${this.alpha})`;
        ctx.fill();
    }
}

// 烟花发射器(增加上升轨迹)
class Firework {
    constructor(targetX, targetY) {
        this.x = Math.random()*canvas.width;
        this.y = canvas.height;
        this.targetY = targetY || canvas.height/3;
        this.particles = [];
        this.speed = -12; // 提升上升速度
        this.exploded = false;
    }

    update() {
        if (!this.exploded) {
            this.y += this.speed;
            if (this.y <= this.targetY) this.explode();
        } else {
            this.particles.forEach(p => p.update());
            this.particles = this.particles.filter(p => p.alpha > 0);
        }
    }

    explode() {
        this.exploded = true;
        const heartPoints = generateHeartPoints(this.x, this.y);
        heartPoints.forEach(point => {
            this.particles.push(new Particle(this.x, this.y, point));
        });
    }

    draw() {
        if (!this.exploded) {
            // 绘制上升轨迹
            ctx.beginPath();
            ctx.arc(this.x, this.y, 3, 0, Math.PI*2);
            ctx.fillStyle = `hsla(${Math.random()*360},100%,60%,1)`;
            ctx.fill();
        } else {
            this.particles.forEach(p => p.draw());
        }
    }
}

// 控制系统(优化自动模式)
let fireworks = [];
modeBtn.addEventListener('click', () => {
    isAutoMode = !isAutoMode;
    modeBtn.textContent = isAutoMode ? '手动模式' : '自动模式';
});

canvas.addEventListener('click', e => {
    fireworks.push(new Firework(e.clientX, e.clientY));
});

// 动画循环(性能优化)
function animate() {
    ctx.fillStyle = 'rgba(0,0,0,0.08)';
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    // 自动模式生成(限制最大数量)
    if(isAutoMode && fireworks.length < 4 && Math.random() < 0.04) {
        fireworks.push(new Firework());
    }

    fireworks.forEach((fw, index) => {
        fw.update();
        fw.draw();
        if (fw.exploded && fw.particles.length === 0) {
            fireworks.splice(index, 1);
        }
    });
    requestAnimationFrame(animate);
}
resizeCanvas();
window.addEventListener('resize', resizeCanvas);
animate();

// 画布尺寸自适应
function resizeCanvas() {
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
}
</script>
</body>
</html>

http://www.xdnf.cn/news/1485.html

相关文章:

  • # 构建和训练一个简单的CBOW词嵌入模型
  • GCoNet+:更强大的团队协作 Co-Salient 目标检测器 2023 GCoNet+(总结)
  • 【Deepseek学习大模型推理】MOONCAKE: A KVCache-centric Architecture调度(中)调度
  • win10 快速搭建 lnmp+swoole 环境 ,部署laravel6 与 swoole框架laravel-s项目3
  • 代码随想录算法训练营第二十五天
  • 卡方检验(Chi-square test)
  • 奇安信春招面试题
  • 在线测试来料公差
  • Java工厂模式解析:三种实现与最佳实践
  • 03-Java入门-JDK的安装和下载
  • 【KWDB 创作者计划】_上位机知识篇---PlatformIO
  • 用 Firebase 和 WebRTC 快速搭建一款浏览器视频聊天应用
  • 布布のC语言课堂——第一讲:揭开C语言的神秘面纱
  • 【KWDB 创作者计划】_深度学习篇---归一化反归一化
  • QtDesigner入门
  • bert4keras
  • mybatis框架补充
  • Spring JDBC 的开发步骤(非注解方式)
  • HashedWheelTimer源码分析
  • 网络安全中Base64编码到后端是何解了
  • 图解Mysql原理:深入理解事务的特性以及它的实现机制
  • IDEA设置手动代理,用户名密码被加密无法通过代码修改的解决方案
  • 4082P 信号/频谱分析仪
  • Javase 基础入门 —— 03 面向对象编程
  • (三)垂直分库架构、分布式数据库
  • MySQL 锁机制
  • 【EasyPan】MySQL FIELD() 函数实现自定义排序
  • [KVM] KVM挂起状态恢复失败与KVM存储池迁移
  • Geek强大的电脑卸载软件工具,免费下载
  • 逻辑漏洞安全