【趣味Html】第11课:动态闪烁发光粒子五角星

news2025/6/7 15:20:19

打造炫酷的动态闪烁发光粒子五角星效果

在这里插入图片描述

前言

在现代Web开发中,视觉效果的重要性不言而喻。今天我们将深入探讨如何使用HTML5 Canvas和JavaScript创建一个令人惊艳的动态闪烁发光粒子五角星效果。这个项目不仅展示了Canvas的强大功能,还涉及了粒子系统、动画循环、数学计算等多个技术要点。

项目概述

我们创建的效果包含以下特性:

  • 🌟 自动旋转的五角星
  • ✨ 动态发光效果(呼吸灯效果)
  • 🎆 粒子系统(从五角星边缘发射粒子)
  • 🎮 鼠标交互(靠近时产生更多粒子)
  • 📱 响应式设计

技术架构

1. 基础结构

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>动态闪烁发光粒子五角星</title>
    <style>
        body {
            margin: 0;
            padding: 0;
            background: #000;
            overflow: hidden;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
        }
        canvas {
            border: 1px solid #333;
        }
    </style>
</head>
<body>
    <canvas id="starCanvas"></canvas>
</body>
</html>

2. 核心类设计

Particle 类(粒子系统)

粒子类是整个效果的核心组件之一,负责创建和管理单个粒子的行为:

class Particle {
    constructor(x, y) {
        this.x = x;                                    // 粒子位置
        this.y = y;
        this.vx = (Math.random() - 0.5) * 2;          // 随机速度
        this.vy = (Math.random() - 0.5) * 2;
        this.life = 1;                                // 生命值
        this.decay = Math.random() * 0.02 + 0.005;    // 衰减速度
        this.size = Math.random() * 3 + 1;            // 粒子大小
        this.color = {                                // 随机颜色
            r: Math.random() * 100 + 155,
            g: Math.random() * 100 + 155,
            b: Math.random() * 100 + 155
        };
    }
    
    update() {
        this.x += this.vx;        // 更新位置
        this.y += this.vy;
        this.life -= this.decay;  // 减少生命值
        this.size *= 0.99;        // 缩小粒子
    }
    
    draw() {
        // 绘制发光效果和粒子本体
    }
}

设计要点:

  • 使用随机值创建自然的粒子运动
  • 生命周期管理确保粒子会自然消失
  • 渐变发光效果增强视觉冲击力
Star 类(五角星系统)

五角星类管理五角星的绘制、旋转和粒子生成:

class Star {
    constructor(x, y, size) {
        this.x = x;
        this.y = y;
        this.size = size;
        this.rotation = 0;              // 旋转角度
        this.glowIntensity = 0;         // 发光强度
        this.glowDirection = 1;         // 发光方向
        this.particles = [];            // 粒子数组
        this.lastParticleTime = 0;      // 上次生成粒子的时间
    }
    
    getStarPoints() {
        // 计算五角星的10个顶点坐标
        const points = [];
        const outerRadius = this.size;
        const innerRadius = this.size * 0.4;
        
        for (let i = 0; i < 10; i++) {
            const angle = (i * Math.PI) / 5 + this.rotation;
            const radius = i % 2 === 0 ? outerRadius : innerRadius;
            const x = this.x + Math.cos(angle) * radius;
            const y = this.y + Math.sin(angle) * radius;
            points.push({ x, y });
        }
        
        return points;
    }
}

核心算法解析

1. 五角星顶点计算

五角星的绘制是基于数学计算的。一个标准五角星有10个顶点(5个外顶点和5个内顶点):

// 五角星顶点计算公式
for (let i = 0; i < 10; i++) {
    const angle = (i * Math.PI) / 5 + this.rotation;  // 每个顶点间隔36度
    const radius = i % 2 === 0 ? outerRadius : innerRadius;
    const x = centerX + Math.cos(angle) * radius;
    const y = centerY + Math.sin(angle) * radius;
}

数学原理:

  • 五角星的外角为36°(2π/10)
  • 内外半径比例约为0.4,创造最佳视觉效果
  • 通过旋转角度实现动态旋转

2. 粒子生成策略

粒子的生成采用了多种策略来创造丰富的视觉效果:

generateParticles() {
    const points = this.getStarPoints();
    
    // 策略1:在五角星边缘生成粒子
    for (let i = 0; i < points.length; i++) {
        const point = points[i];
        const nextPoint = points[(i + 1) % points.length];
        
        // 线性插值在边缘随机位置生成粒子
        const t = Math.random();
        const x = point.x + (nextPoint.x - point.x) * t;
        const y = point.y + (nextPoint.y - point.y) * t;
        
        if (Math.random() < 0.3) {
            this.particles.push(new Particle(x, y));
        }
    }
    
    // 策略2:在顶点生成更多粒子
    for (let i = 0; i < points.length; i += 2) {
        const point = points[i];
        if (Math.random() < 0.5) {
            this.particles.push(new Particle(point.x, point.y));
        }
    }
}

3. 发光效果实现

发光效果通过Canvas的阴影和渐变功能实现:

// 动态发光强度
this.glowIntensity += this.glowDirection * 0.02;
if (this.glowIntensity >= 1 || this.glowIntensity <= 0) {
    this.glowDirection *= -1;  // 反向,创造呼吸效果
}

// 应用发光效果
ctx.shadowColor = `rgba(255, 255, 100, ${this.glowIntensity})`;
ctx.shadowBlur = 20 + this.glowIntensity * 30;

性能优化技巧

1. 粒子生命周期管理

// 高效的粒子清理
this.particles = this.particles.filter(particle => {
    particle.update();
    return particle.life > 0;  // 只保留活着的粒子
});

2. 时间控制的粒子生成

// 避免每帧都生成粒子,控制生成频率
const now = Date.now();
if (now - this.lastParticleTime > 50) {
    this.generateParticles();
    this.lastParticleTime = now;
}

3. 渐进式画布清理

// 使用半透明矩形而非完全清除,创造拖尾效果
ctx.fillStyle = 'rgba(0, 0, 0, 0.1)';
ctx.fillRect(0, 0, canvas.width, canvas.height);

交互设计

鼠标交互

canvas.addEventListener('mousemove', (e) => {
    const rect = canvas.getBoundingClientRect();
    const mouseX = e.clientX - rect.left;
    const mouseY = e.clientY - rect.top;
    
    stars.forEach(star => {
        const dx = mouseX - star.x;
        const dy = mouseY - star.y;
        const distance = Math.sqrt(dx * dx + dy * dy);
        
        if (distance < 150) {
            // 鼠标靠近时增加粒子生成
            for (let i = 0; i < 3; i++) {
                const angle = Math.random() * Math.PI * 2;
                const radius = Math.random() * star.size;
                const x = star.x + Math.cos(angle) * radius;
                const y = star.y + Math.sin(angle) * radius;
                star.particles.push(new Particle(x, y));
            }
        }
    });
});

响应式设计

window.addEventListener('resize', () => {
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    
    // 重新定位五角星
    stars.forEach((star, i) => {
        star.x = canvas.width / 4 + (i * canvas.width / 4);
        star.y = canvas.height / 2 + Math.sin(i * 2) * 100;
    });
});

扩展可能性

1. 颜色主题

可以添加多种颜色主题,让用户选择不同的视觉风格:

const themes = {
    golden: { r: 255, g: 215, b: 0 },
    blue: { r: 100, g: 150, b: 255 },
    purple: { r: 200, g: 100, b: 255 }
};

2. 音频响应

可以集成Web Audio API,让粒子效果响应音频频率:

// 伪代码
const audioContext = new AudioContext();
// 根据音频频率调整粒子生成速度和五角星大小

3. 3D效果

使用WebGL或Three.js可以将效果扩展到3D空间。

总结

这个动态闪烁发光粒子五角星项目展示了现代Web技术的强大能力。通过合理的类设计、数学计算、性能优化和交互设计,我们创造了一个既美观又高效的视觉效果。

关键技术点:

  • Canvas 2D API的高级应用
  • 面向对象的JavaScript设计
  • 数学在图形编程中的应用
  • 性能优化策略
  • 用户交互设计

这个项目不仅可以作为学习Canvas和JavaScript的优秀案例,也可以作为更复杂视觉效果的基础框架。希望这篇博客能够帮助你理解现代Web图形编程的精髓,并激发你创造更多令人惊艳的视觉效果!

源码

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>动态闪烁发光粒子五角星</title>
    <style>
        body {
            margin: 0;
            padding: 0;
            background: #000;
            overflow: hidden;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
        }
        canvas {
            border: 1px solid #333;
        }
    </style>
</head>
<body>
    <canvas id="starCanvas"></canvas>
    
    <script>
        const canvas = document.getElementById('starCanvas');
        const ctx = canvas.getContext('2d');
        
        // 设置画布大小
        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;
        
        // 粒子类
        class Particle {
            constructor(x, y) {
                this.x = x;
                this.y = y;
                this.vx = (Math.random() - 0.5) * 2;
                this.vy = (Math.random() - 0.5) * 2;
                this.life = 1;
                this.decay = Math.random() * 0.02 + 0.005;
                this.size = Math.random() * 3 + 1;
                this.color = {
                    r: Math.random() * 100 + 155,
                    g: Math.random() * 100 + 155,
                    b: Math.random() * 100 + 155
                };
            }
            
            update() {
                this.x += this.vx;
                this.y += this.vy;
                this.life -= this.decay;
                this.size *= 0.99;
            }
            
            draw() {
                ctx.save();
                ctx.globalAlpha = this.life;
                
                // 创建发光效果
                const gradient = ctx.createRadialGradient(
                    this.x, this.y, 0,
                    this.x, this.y, this.size * 3
                );
                gradient.addColorStop(0, `rgba(${this.color.r}, ${this.color.g}, ${this.color.b}, 1)`);
                gradient.addColorStop(0.5, `rgba(${this.color.r}, ${this.color.g}, ${this.color.b}, 0.5)`);
                gradient.addColorStop(1, `rgba(${this.color.r}, ${this.color.g}, ${this.color.b}, 0)`);
                
                ctx.fillStyle = gradient;
                ctx.beginPath();
                ctx.arc(this.x, this.y, this.size * 3, 0, Math.PI * 2);
                ctx.fill();
                
                // 绘制核心粒子
                ctx.fillStyle = `rgba(${this.color.r}, ${this.color.g}, ${this.color.b}, 1)`;
                ctx.beginPath();
                ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
                ctx.fill();
                
                ctx.restore();
            }
        }
        
        // 五角星类
        class Star {
            constructor(x, y, size) {
                this.x = x;
                this.y = y;
                this.size = size;
                this.rotation = 0;
                this.glowIntensity = 0;
                this.glowDirection = 1;
                this.particles = [];
                this.lastParticleTime = 0;
            }
            
            // 计算五角星的顶点
            getStarPoints() {
                const points = [];
                const outerRadius = this.size;
                const innerRadius = this.size * 0.4;
                
                for (let i = 0; i < 10; i++) {
                    const angle = (i * Math.PI) / 5 + this.rotation;
                    const radius = i % 2 === 0 ? outerRadius : innerRadius;
                    const x = this.x + Math.cos(angle) * radius;
                    const y = this.y + Math.sin(angle) * radius;
                    points.push({ x, y });
                }
                
                return points;
            }
            
            update() {
                this.rotation += 0.01;
                
                // 更新发光强度
                this.glowIntensity += this.glowDirection * 0.02;
                if (this.glowIntensity >= 1 || this.glowIntensity <= 0) {
                    this.glowDirection *= -1;
                }
                
                // 生成粒子
                const now = Date.now();
                if (now - this.lastParticleTime > 50) {
                    this.generateParticles();
                    this.lastParticleTime = now;
                }
                
                // 更新粒子
                this.particles = this.particles.filter(particle => {
                    particle.update();
                    return particle.life > 0;
                });
            }
            
            generateParticles() {
                const points = this.getStarPoints();
                
                // 在五角星边缘生成粒子
                for (let i = 0; i < points.length; i++) {
                    const point = points[i];
                    const nextPoint = points[(i + 1) % points.length];
                    
                    // 在边缘随机位置生成粒子
                    const t = Math.random();
                    const x = point.x + (nextPoint.x - point.x) * t;
                    const y = point.y + (nextPoint.y - point.y) * t;
                    
                    if (Math.random() < 0.3) {
                        this.particles.push(new Particle(x, y));
                    }
                }
                
                // 在五角星顶点生成更多粒子
                for (let i = 0; i < points.length; i += 2) {
                    const point = points[i];
                    if (Math.random() < 0.5) {
                        this.particles.push(new Particle(point.x, point.y));
                    }
                }
            }
            
            draw() {
                const points = this.getStarPoints();
                
                // 绘制发光效果
                ctx.save();
                ctx.shadowColor = `rgba(255, 255, 100, ${this.glowIntensity})`;
                ctx.shadowBlur = 20 + this.glowIntensity * 30;
                
                // 绘制五角星主体
                ctx.fillStyle = `rgba(255, 255, 150, ${0.8 + this.glowIntensity * 0.2})`;
                ctx.strokeStyle = `rgba(255, 255, 200, ${0.9 + this.glowIntensity * 0.1})`;
                ctx.lineWidth = 2;
                
                ctx.beginPath();
                ctx.moveTo(points[0].x, points[0].y);
                for (let i = 1; i < points.length; i++) {
                    ctx.lineTo(points[i].x, points[i].y);
                }
                ctx.closePath();
                ctx.fill();
                ctx.stroke();
                
                ctx.restore();
                
                // 绘制粒子
                this.particles.forEach(particle => particle.draw());
            }
        }
        
        // 创建多个五角星
        const stars = [];
        const numStars = 3;
        
        for (let i = 0; i < numStars; i++) {
            const x = canvas.width / 4 + (i * canvas.width / 4);
            const y = canvas.height / 2 + Math.sin(i * 2) * 100;
            const size = 50 + Math.random() * 30;
            stars.push(new Star(x, y, size));
        }
        
        // 动画循环
        function animate() {
            // 清除画布
            ctx.fillStyle = 'rgba(0, 0, 0, 0.1)';
            ctx.fillRect(0, 0, canvas.width, canvas.height);
            
            // 更新和绘制所有五角星
            stars.forEach(star => {
                star.update();
                star.draw();
            });
            
            requestAnimationFrame(animate);
        }
        
        // 窗口大小调整
        window.addEventListener('resize', () => {
            canvas.width = window.innerWidth;
            canvas.height = window.innerHeight;
            
            // 重新定位五角星
            stars.forEach((star, i) => {
                star.x = canvas.width / 4 + (i * canvas.width / 4);
                star.y = canvas.height / 2 + Math.sin(i * 2) * 100;
            });
        });
        
        // 鼠标交互
        canvas.addEventListener('mousemove', (e) => {
            const rect = canvas.getBoundingClientRect();
            const mouseX = e.clientX - rect.left;
            const mouseY = e.clientY - rect.top;
            
            stars.forEach(star => {
                const dx = mouseX - star.x;
                const dy = mouseY - star.y;
                const distance = Math.sqrt(dx * dx + dy * dy);
                
                if (distance < 150) {
                    // 鼠标靠近时增加粒子生成
                    for (let i = 0; i < 3; i++) {
                        const angle = Math.random() * Math.PI * 2;
                        const radius = Math.random() * star.size;
                        const x = star.x + Math.cos(angle) * radius;
                        const y = star.y + Math.sin(angle) * radius;
                        star.particles.push(new Particle(x, y));
                    }
                }
            });
        });
        
        // 开始动画
        animate();
    </script>
</body>
</html>

如果你觉得这个效果有趣,不妨尝试修改参数,创造属于你自己的独特效果!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2399571.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CFTel:一种基于云雾自动化的鲁棒且可扩展的远程机器人架构

中文标题&#xff1a; CFTel&#xff1a;一种基于云雾自动化的鲁棒且可扩展的远程机器人架构 英文标题&#xff1a; CFTel: A Practical Architecture for Robust and Scalable Telerobotics with Cloud-Fog Automation 作者信息 Thien Tran, Jonathan Kua, Minh Tran, Hongh…

Educational Codeforces Round 179 (Rated for Div. 2)

CF2111,简单手速场 A. Energy Crystals 贪心&#xff0c;每次最小值会乘2&#xff0c;直接模拟即可&#xff0c;复杂度 O ( log ⁡ n ) O(\log n) O(logn) void solve(){int x;cin>>x;multiset<int> s{0,0,0};int res0;while(*s.begin()<x){int x*s.begin();s…

完成一个可交互的k8s管理平台的页面开发

使用deepseek完成设计一个k8s管理平台&#xff0c;关键词如下&#xff1a; 完成一个可交互的k8s管理平台的页面开发Kubernetes 管理平台页面设计 下面是一个基于现代Web技术的可交互Kubernetes管理平台的页面设计方案&#xff0c;使用React作为前端框架&#xff0c;配合Ant De…

Windows系统工具:WinToolsPlus 之 SQL Server 日志清理

使用软件时提示数据库事务日志已满&#xff0c; 使用WinToolsPlus 数据库页签 先设置 数据源 &#xff0c; 选择 需要清理日志的数据库&#xff0c; 点击 数据库日志清理 即可。 下载地址&#xff1a; http://v.s3.sh.cn/archives/2279.html

在Windows11上安装 Ubuntu WSL

不想安装虚拟机,想在Windows11上运行Linux。网上虽有教程,但是图片明显都是老图,与Windows11还是有些差异。网上缺乏一个齐全的真正的Windows11运行Linux的教程。 一、在Windows上的设置 1. 在window11的搜索框内(所有你找不到的应用都可以用这个搜索功能)&#xff0c;搜索&q…

嵌入式Linux之RK3568

系统烧写镜像。 1、直接使用正点原子官方的updata.img(MIDP) 进入瑞芯微发开工具RKDevTool&#xff0c;选择升级固件&#xff0c;上传到固件&#xff0c;记住这里要进入maskrom模式或者是loader模式&#xff0c;进入该模式之后点击升级即可。 2、烧入自己制作的镜像(单独、一…

JavaScript性能优化实战技术

目录 性能优化核心原则 代码层面优化 加载优化策略 内存管理实践 及时解除事件监听 避免内存泄漏模式 渲染性能调优 使用requestAnimationFrame优化动画 批量DOM操作减少回流 性能监控工具 现代API应用 缓存策略实施 性能优化核心原则 减少资源加载时间 避免阻塞主…

网页前端开发(基础进阶3--Vue)

Vue3 Vue是一款用于构建用户界面的渐进式的JavaScript框架。 Vue由2部分组成&#xff1a;Vue核心包&#xff0c;Vue插件包 Vue核心包包含&#xff1a;声明式渲染&#xff0c;组件系统。 Vue插件包&#xff1a;VueRouter&#xff08;客户端路由&#xff09;&#xff0c;Vuex…

tryhackme——Abusing Windows Internals(进程注入)

文章目录 一、Abusing Processes二、进程镂空三、线程劫持四、DLL注入五、Memory Execution Alternatives 一、Abusing Processes 操作系统上运行的应用程序可以包含一个或多个进程&#xff0c;进程表示正在执行的程序。进程包含许多其他子组件&#xff0c;并且直接与内存或虚…

基于 Alpine 定制单功能用途(kiosk)电脑

前言 故事回到 7 年前, 在网上冲浪的时候发现了一篇介绍使用 Ubuntu 打造 kiosk 单功能用途电脑的文章, 挺好玩的, 就翻译了一下并比葫芦画瓢先后用了 CentOS 7, ArchLinux 进行了实现. 历史文章: 翻译 - 使用Ubutnu14.04和Chrome打造单功能用途电脑(大屏展示电脑) 使用CentOS…

知识图谱系统功能实现,技术解决方案,附源码

基于Java、Neo4j和ElasticSearch构建的医疗知识图谱知识库&#xff0c;是一个融合图数据库技术与搜索引擎的智能化医疗知识管理系统。该系统以Neo4j图数据库为核心&#xff0c;利用其高效的图结构存储能力&#xff0c;将疾病、症状、药品、检查项目、科室等医疗实体抽象为节点&…

洛谷P12610 ——[CCC 2025 Junior] Donut Shop

题目背景 Score: 15. 题目描述 The owner of a donut shop spends the day baking and selling donuts. Given the events that happen over the course of the day, your job is to determine the number of donuts remaining when the shop closes. 输入格式 The first …

1. 数据库基础

1.1 什么是数据库 ⭐ mysql 本质是一种网络服务, 是基于 C(mysql) S(mysqld)的 网络服务. 存储数据用文件就可以了&#xff0c;为什么还要弄个数据库&#xff1f;文件保存数据存在以下缺点&#xff1a; 文件的安全性问题。文件不利于数据查询和管理。文件不利于存储海量数据。…

英伟达288GB HBM4+50P算力

英伟达CEO黄仁勋在COMPUTEX 2025上突然官宣&#xff1a;以暗物质研究先驱Vera Rubin命名的新一代AI芯片即将量产&#xff01;这颗被称作“算力巨兽”的Rubin GPU&#xff0c;不仅搭载288GB HBM4显存和50 Petaflops推理算力&#xff0c;更携三大颠覆性技术直击AI行业痛点。更可怕…

综合案例:斗地主

综合案例&#xff1a;斗地主 1.程序概述 这是一个模拟斗地主游戏发牌过程的C语言程序&#xff0c;实现了扑克牌的初始化、洗牌和发牌功能。 2.功能需求 2.1 扑克牌定义 使用结构体 Card 表示一张牌&#xff0c;包含&#xff1a; 花色属性suit&#xff08;0-3表示普通花色♥…

前端组件推荐 Swiper 轮播与 Lightbox 灯箱组件深度解析

在互联网产品不断迭代升级的今天&#xff0c;用户对于页面交互和视觉效果的要求越来越高。想要快速打造出吸睛又实用的项目&#xff0c;合适的组件必不可少。今天就为大家推荐两款超好用的组件 ——Swiper 轮播组件和 Lightbox 灯箱组件&#xff0c;轻松解决你的展示难题&#…

Deepfashion2 数据集使用笔记

目录 数据类别: 筛选类别数据: 验证精度筛选前2个类别: 提取类别数据 可视化类别数据: Deepfashion2 的解压码 旋转数据增强 数据类别: 类别含义: Class idx类别名称英文名称0短上衣short sleeve top1长上衣long sleeve top2短外套short sleeve outwear3长外套lo…

Dify知识库下载小程序

一、Dify配置 1.查看或创建知识库的API 二、下载程序配置 1. 安装依赖resquirements.txt ######requirements.txt##### flask2.3.3 psycopg2-binary2.9.9 requests2.31.0 python-dotenv1.0.0#####安装依赖 pip3 install -r requirements.txt -i https://pypi.tuna.tsinghua.…

数据库中求最小函数依赖集-最后附解题过程

今天来攻克数据库设计里一个超重要的知识点 —— 最小函数依赖集。对于刚接触数据库的小白来说&#xff0c;这概念可能有点绕&#xff0c;但别担心&#xff0c;咱们一步步拆解&#xff0c;轻松搞定&#x1f4aa;&#xff01; &#xff08;最后fuyou&#xff09; 什么是最小函数…

嵌入式系统中常用的开源协议

目录 1、GNU通用公共许可证&#xff08;GPL&#xff09; 2、GNU宽松通用公共许可证&#xff08;LGPL&#xff09; 3、MIT许可证 4、Apache许可证2.0 5、BSD许可证 6、如何选择合适的协议 在嵌入式系统开发中&#xff0c;开源软件的使用已成为主流趋势。从物联网设备到汽车…