烟花模拟器:满屏流光炸开,过年气氛一秒拉满
烟花最好看的是炸开的那一瞬间,但平时很难随手放一场。这个烟花模拟器把夜空、星点和爆炸拖尾都搬进浏览器:点哪里哪里就炸,也会在夜空自动随机绽放;一次能连发 6 发,8 套配色一键切换,爆炸形态分成散花、圆环、柳树三种。先看成品,再讲这个单文件应用是怎么用一段需求让码道 WebUI 生成并部署出来的。

为什么值得看
烟花的本质是一套粒子系统:一颗火箭升到目标点后炸散成几十个带速度的粒子,重力把它们往下拉,流光拖尾靠半透明残影一层层叠出来。把爆炸形态、配色、连发都做成可调项之后,粒子系统的「出生—更新—消亡」这条主线比看教程直观得多。这个工具适合想理解 Canvas 动画又不想先啃一整套引擎的人。
任务描述
在码道 WebUI 输入框粘贴以下需求,回车发送:
开发一个烟花秀模拟器网页应用:深色夜空背景,烟花可以在夜空随机自动绽放,也支持点击画面手动放烟花;烟花要有彩色粒子、流光拖尾、重力下落和轻微闪烁,支持切换配色并一键连发多个烟花;界面简洁美观,单个 index.html 即跑即玩。完成后自动部署成可访问的网页应用,并把访问地址写出来。
码道实际做了什么
我没有让它手写每一步,只说清楚最终效果。它这轮的动作是:
- 在工作目录下新建项目目录,写入单文件
index.html,随后又做了几次增删改,把爆炸形态、配色和连发逻辑补齐。 - 从页面里提取内嵌 JavaScript,用
node --check做语法检查,确认没有语法错误。 - 探测空闲端口(这轮是 3000),用
python3 -m http.server启动静态服务,curl自检 HTTP 200 后给出内部预览地址。 - 最后把功能清单、文件位置和访问地址一起写回对话,预览地址就在对话末尾。
代码亮点
1. 随机工具:所有随机范围都走同一行
爆炸点、星点大小、闪烁相位都复用这两个函数,避免到处写 Math.random():
const rand = (a, b) => a + Math.random() * (b - a);
const pick = arr => arr[(Math.random() * arr.length) | 0];
2. 三种爆炸形态靠随机阈值分流
同一发火箭升到目标点,按随机值切成散花、圆环、柳树三种形态:
function launch(targetX, targetY) {
const palette = PALETTES[paletteIdx].colors;
const type = Math.random();
const opts = {
x: targetX == null ? rand(W * 0.12, W * 0.88) : targetX,
y: H + rand(0, 40),
tx: targetY == null ? rand(H * 0.12, H * 0.5) : targetY,
colors: palette,
kind: type < 0.55 ? 'burst' : type < 0.82 ? 'ring' : 'willow',
};
rockets.push(new Rocket(opts));
}
3. 拖尾用半透明覆盖代替 clearRect
每一帧不把画布彻底擦干净,而是铺一层几乎透明的深色,上一帧的粒子就自然留下残影;粒子数组从后往前遍历,删除时可以安全 splice:
function frame(now) {
const t = now * 0.001;
ctx.fillStyle = 'rgba(5,6,15,0.28)';
ctx.fillRect(0, 0, W, H);
drawStars(t);
for (let i = rockets.length - 1; i >= 0; i--) {
if (!rockets[i].update()) rockets.splice(i, 1);
}
for (let i = particles.length - 1; i >= 0; i--) {
if (!particles[i].update()) particles.splice(i, 1);
}
自动放烟花也不是 setInterval 写死,而是每次随机 0.9–2.2 秒再排下一次:
function scheduleAuto() {
clearTimeout(autoTimer);
if (!autoEnabled) return;
autoTimer = setTimeout(() => {
launch();
scheduleAuto();
}, rand(900, 2200));
}
验证与踩坑
- 生成结束后打开对话里的内部预览地址,页面标题是「烟花模拟器」,烟花确实会自动炸开。
- 隔几秒连截两张运行画面,两个文件内容不重复:自动烟花的时间间隔是随机数,画面本来就一直在变。
- 踩坑:内部预览链接偶发跳到开发者空间登录跳转页,重新打开一次才稳定进入应用。截图前先确认页面标题或 Canvas 已经出现,避免截到空白页。
- 从代码看,拖尾浓淡由
rgba(5,6,15,0.28)的 alpha 决定;这个值越低屏幕越难清干净,越高拖尾越短。这是最容易调出「炸完就糊成一团」的地方。
本地复现
项目是单文件 index.html,没有第三方依赖。把文件保存到本地后直接用浏览器打开就能玩;如果想通过本地 HTTP 服务访问:
cd codearts-fireworks-sky
python3 -m http.server 8080
# 然后打开 http://127.0.0.1:8080
直接下载试玩
源码同步到公开 Demo Park 仓库:
- Demo Park 仓库:https://atomgit.com/deli007/demo_park
- 本案例目录:https://atomgit.com/deli007/demo_park/tree/main/codearts-fireworks-sky
准备环境:进入 AI 开发者空间
本文用码道 WebUI 版演示。先进入 AI 开发者空间并选择体验版,不需要本地安装:
- 浏览器打开 https://devstation.developer.huaweicloud.com/aidevspace?utm_source=opcsfsq&utm_medium=wbwz
- 弹窗「请选择要进入的版本」→ 点击 体验版
- 首次使用跳到华为云登录页,登录一次后浏览器会话可复用
- 弹窗「临时凭据自动配置」→ 点击 同意,沙箱自动创建
进入主界面后,等左侧菜单加载出来,找到 CodeArts,点它右侧的浏览器图标,就打开了码道 WebUI 对话窗口。

开通后有三种使用方式:WebUI(浏览器对话)、TUI(终端命令行)和桌面 IDE(IDE 插件)。本文用 WebUI 版演示。
进入 CodeArts:https://developer.huaweicloud.com/codeartsco.html?source=dmzntgwsf&sourcead=dmzntgwwbwz

使用码道体会
最省事的是「部署」这步:以前写单文件小工具,写完还要自己开本地服务、找端口;这次让它在需求里顺带把服务起好,拿到 URL 就能在浏览器里看。生成过程中它还会自己跑一遍 JS 语法检查,出错先修再往下走,比直接扔给我一坨代码再让我 debug 舒服。不足是内部预览链接有偶发跳转,需要重开一次;体验版环境 3 小时会释放,所以要记得立刻保存 index.html 和截图。
总结
烟花模拟器把粒子系统的核心链路浓缩成一个单文件:随机工具负责所有不确定性,launch() 负责火箭与爆炸形态,frame() 用半透明覆盖制造流光拖尾。8 套配色和连发按钮让「放烟花」这件小事变得有按钮可按。后续可以加音效、慢动作回放,或者把爆炸形态做成可勾选项,让一场烟花能按自己的顺序来。
烟花模拟器运行效果对照
连续截取的两个运行画面,左边是自动烟花炸开瞬间,右边是数秒后的另一帧:

- 点赞
- 收藏
- 关注作者
评论(0)