跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Python

基于Canvas和Web Audio API的交互式烟花动画网页游戏

> 一个基于 Canvas 和 Web Audio API 的交互式烟花动画网页 * * 目录 整体架构 HTML 结构 CSS 样式 JavaScript 核心模块 用户交互 性能优化 iOS 适配 文件依赖 * * 一、整体架构 * * 二、HTML 结构部分 1\. 头部元信息 **说明:** 设置字符编码为 UTF-8 页面标题显示新年祝福 viewport-fit=cover 适配 iP…

剑仙发布于 2026/4/7更新于 2026/9/1022K 浏览
基于Canvas和Web Audio API的交互式烟花动画网页游戏

一个基于 Canvas 和 Web Audio API 的交互式烟花动画网页


目录

  1. 整体架构
  2. HTML 结构
  3. CSS 样式
  4. JavaScript 核心模块
  5. 用户交互
  6. 性能优化
  7. iOS 适配
  8. 文件依赖

一、整体架构

┌─────────────────────────────────────────────────────────────┐ │ HTML 结构 │ ├─────────────────────────────────────────────────────────────┤ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │ │ │ SVG 图标 │ │ Canvas容器 │ │ 控制面板/菜单 │ │ │ └─────────────┘ └─────────────┘ └─────────────────────┘ │ ├─────────────────────────────────────────────────────────────┤ │ CSS 样式 │ ├─────────────────────────────────────────────────────────────┤ │ JavaScript 逻辑 │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐ │ │ │ FireworkSound│ │ Store │ │ Shell/Star/Spark │ │ │ │ 音效模块 │ │ 状态管理 │ │ 粒子系统 │ │ │ └──────────────┘ └──────────────┘ └──────────────────────┘ │ └─────────────────────────────────────────────────────────────┘ 

二、HTML 结构部分

1. 头部元信息
<metacharset="UTF-8"><title>2026新年快乐!万事如意!</title><metaname="viewport"content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover">

说明:

  • 设置字符编码为 UTF-8
  • 页面标题显示新年祝福
  • viewport-fit=cover 适配 iPhone X 系列刘海屏
  • 禁用用户缩放,防止误操作
2. iOS PWA 支持
<metaname="apple-mobile-web-app-capable"content="yes"><metaname="apple-mobile-web-app-status-bar-style"content="black-translucent"><metaname="apple-mobile-web-app-title"content="烟花盛宴"><linkrel="apple-touch-icon"href="..."><linkrel="manifest"href="data:application/json;base64,...">

说明:

  • 支持添加到 iOS 主屏幕
  • 半透明状态栏适配刘海屏
  • 内联 PWA manifest(Base64 编码)
3. SVG 图标定义
<svgxmlns="http://www.w3.org/2000/svg"><symbolid="icon-play"viewBox="0 0 24 24"><pathd="M8 5v14l11-7z"/></symbol><symbolid="icon-pause"viewBox="0 0 24 24"><pathd="M6 19h4V5H6v14zm8-14v14h4V5h-4z"/></symbol><symbolid="icon-close"viewBox="0 0 24 24">...</symbol><symbolid="icon-settings"viewBox="0 0 24 24">...</symbol><symbolid="icon-shutter-fast"viewBox="0 0 24 24">...</symbol><symbolid="icon-shutter-slow"viewBox="0 0 24 24">...</symbol></svg>

说明:

  • 使用 SVG symbol 定义可复用的图标
  • 通过 <use href="#icon-xxx"> 引用
  • 优点:矢量图标、可缩放、体积小
4. Canvas 画布容器
<divid="canvas-container"><canvasid="trails-canvas"></canvas><!-- 拖尾轨迹层 --><canvasid="main-canvas"></canvas><!-- 主画面层 --></div>

双层 Canvas 设计原理:

层级作用渲染方式
trails-canvas绘制烟花拖尾效果渐变透明覆盖实现残影
main-canvas绘制当前帧的粒子和UI元素每帧清空重绘
5. 控制面板
<divid="controls"><divid="pause-btn"class="btn"><svgfill="white"width="24"height="24"><usehref="#icon-pause"></use></svg></div><divid="shutter-btn"class="btn"><svgfill="white"width="24"height="24"><usehref="#icon-shutter-slow"></use></svg></div><divid="settings-btn"class="btn"><svgfill="white"width="24"height="24"><usehref="#icon-settings"></use></svg></div></div>

按钮功能:

  • 暂停/播放:控制动画运行
  • 快门模式:切换长曝光效果
  • 设置:打开设置菜单
6. 设置菜单
<divid="menu"><divid="menu__header">设置</div><form><divclass="form-option form-option--select"><label>烟花类型</label><selectid="shell-type"></select></div><divclass="form-option form-option--select"><label>烟花大小</label><selectid="shell-size"></select></div><divclass="form-option form-option--checkbox"><label><inputid="auto-launch"type="checkbox"/><span>自动发射</span></label></div><divclass="form-option form-option--checkbox"><label><inputid="finale-mode"type="checkbox"/><span>终场模式</span></label></div><divclass="form-option form-option--checkbox"><label><inputid="hide-controls"type="checkbox"/><span>隐藏控制</span></label></div><divclass="form-option form-option--checkbox"><label><inputid="sound-enabled"type="checkbox"checked/><span>声音效果</span></label></div><divclass="form-option form-option--select"><label>声音类型</label><selectid="sound-type"></select></div></form></div>
7. 首次交互提示(iOS 适配)
<divid="audio-prompt"><divid="audio-prompt__icon">🎆</div><divid="audio-prompt__text">点击屏幕开始烟花盛宴</div><divid="audio-prompt__hint">Tap to start fireworks</div></div>

说明:

  • iOS Safari 要求用户交互后才能播放音频
  • 此提示引导用户点击以解锁音频

三、CSS 样式部分

1. 全局样式与触摸优化
*{position: relative;box-sizing: border-box;-webkit-tap-highlight-color: transparent;/* 移除点击高亮 */-webkit-touch-callout: none;/* 禁用长按菜单 */-webkit-user-select: none;/* 禁止选择文字 */user-select: none;touch-action: manipulation;/* 禁用双击缩放 */}html{background-color: #000;}body{overflow: hidden;color:rgba(255, 255, 255, 0.5);font-family:"Russo One", arial, sans-serif;overscroll-behavior: none;/* 禁用橡皮筋效果 */padding:env(safe-area-inset-top)env(safe-area-inset-right)env(safe-area-inset-bottom)env(safe-area-inset-left);/* 安全区域 */}
2. 混合模式
#canvas-container canvas{position: absolute;mix-blend-mode: lighten;/* 变亮混合模式 */}

说明:

  • lighten 混合模式使亮色粒子在黑色背景上更加突出
  • 多个亮色叠加会产生更亮的效果
3. 动画过渡
.hide{opacity: 0;visibility: hidden;transition: opacity 0.3s, visibility 0.3s;}

说明:

  • 使用 opacity + visibility 组合实现平滑的显示/隐藏动画
  • visibility 延迟隐藏,避免点击穿透
4. 音频提示动画
#audio-prompt__icon{font-size: 80px;animation: pulse 1.5s ease-in-out infinite;}@keyframes pulse{0%, 100%{transform:scale(1);opacity: 1;}50%{transform:scale(1.1);opacity: 0.7;}}

四、JavaScript 核心模块

1. FireworkSound 音效模块
const FireworkSound ={ctx:null,// AudioContext 实例enabled:true,// 是否启用声音soundType:'realistic',// 当前声音类型isUnlocked:false,// iOS 音频解锁状态init(){// 初始化 Web Audio APIthis.ctx =new(window.AudioContext || window.webkitAudioContext)();},unlock(){// iOS 音频解锁:播放静音缓冲区if(this.isUnlocked)returntrue;if(this.ctx.state ==='suspended'){this.ctx.resume();}const buffer =this.ctx.createBuffer(1,1,22050);const source =this.ctx.createBufferSource(); source.buffer = buffer; source.connect(this.ctx.destination); source.start(0);this.isUnlocked =true;},playLaunch(){/* 发射音效 */},playBurst(size){/* 爆炸音效 */}};

Web Audio API 核心概念:

组件作用示例用途
AudioContext音频上下文,管理所有音频节点new AudioContext()
OscillatorNode振荡器,生成周期性波形正弦波、方波、锯齿波
GainNode增益节点,控制音量音量包络、淡入淡出
BiquadFilter双二阶滤波器低通、高通、带通滤波
BufferSource缓冲源,播放采样数据白噪声、爆炸声

真实爆炸声实现原理:

playRealisticBurst(size =1){// 1. 生成白噪声缓冲区const duration =0.6+ size *0.2;const bufferSize =this.ctx.sampleRate * duration;const buffer =this.ctx.createBuffer(1, bufferSize,this.ctx.sampleRate);const data = buffer.getChannelData(0);for(let i =0; i < bufferSize; i++){const t = i / bufferSize;const noise = Math.random()*2-1;// 随机噪声 [-1, 1]const envelope = Math.pow(1- t,1.5);// 指数衰减包络 data[i]= noise * envelope;}// 2. 创建低通滤波器模拟爆炸闷响const filter =this.ctx.createBiquadFilter(); filter.type ='lowpass'; filter.frequency.setValueAtTime(3000* size,this.ctx.currentTime); filter.frequency.exponentialRampToValueAtTime(200,this.ctx.currentTime + duration *0.7);// 3. 音量包络:快速起音,缓慢衰减const gain =this.ctx.createGain(); gain.gain.setValueAtTime(0,this.ctx.currentTime); gain.gain.linearRampToValueAtTime(volume,this.ctx.currentTime +0.02);// 起音 20ms gain.gain.exponentialRampToValueAtTime(0.01,this.ctx.currentTime + duration);// 衰减// 4. 连接节点并播放 noise.connect(filter); filter.connect(gain); gain.connect(this.ctx.destination); noise.start(this.ctx.currentTime);}

声音类型对照表:

类型中文名特点
realistic真实白噪声 + 低频冲击 + 噼啪声
cinematic电影感深沉隆隆声 + 闪烁火花
classic经典烟花清脆爆破声
retro复古8位方波游戏机风格
soft柔和轻柔正弦波轻柔音效
synth电子合成多振荡器合成器
drum鼓点贝斯底鼓 + 军鼓 + 踩镲
whistle哨子爆破口哨式发射 + 爆破
2. Store 状态管理
const store ={_listeners:newSet(),// 订阅者集合state:{paused:false,longExposure:false,menuOpen:false,config:{shell:'Random',size:'3',autoLaunch:true,finale:false,hideControls:false,soundEnabled:true,soundType:'realistic'}},setState(nextState){this.state = Object.assign({},this.state, nextState);this._dispatch();// 通知所有订阅者this.persist();// 持久化到 localStorage},subscribe(listener){this._listeners.add(listener);return()=>this._listeners.delete(listener);},load(){// 从 localStorage 加载配置},persist(){// 保存配置到 localStorage}};

发布-订阅模式流程:

用户操作 → updateConfig() → store.setState() → _dispatch() → renderApp() ↓ 更新 DOM 
3. Shell 烟花类
classShell{constructor(options){this.size = options.size;// 爆炸半径this.starCount = options.starCount;// 星星数量this.starLife = options.starLife;// 星星寿命(毫秒)this.color = options.color;// 颜色this.glitter = options.glitter;// 闪光类型this.pistil = options.pistil;// 是否有花心this.ring = options.ring;// 是否环形}launch(position, launchHeight){// 1. 计算发射位置和目标高度const launchX = position *(width - hpad *2)+ hpad;const launchY = height;const burstY = minHeight -(launchHeight *(minHeight - vpad));const launchDistance = launchY - burstY;// 2. 计算发射速度(抛物线运动近似)const launchVelocity = Math.pow(launchDistance *0.04,0.64);// 3. 创建彗星(上升的火球)const comet = Star.add( launchX, launchY,this.color ||COLOR.White, Math.PI,// 向上发射 launchVelocity, launchVelocity *400// 寿命); comet.heavy =true;// 减少空气阻力 comet.sparkFreq =16;// 火花频率// 4. 设置死亡回调为爆炸 comet.onDeath=()=>this.burst(comet.x, comet.y);// 5. 播放发射音效 FireworkSound.playLaunch();}burst(x, y){// 1. 计算爆炸速度const speed =this.size /96;// 2. 创建粒子弧(圆形分布)createParticleArc(0,PI_2,this.starCount,1,(angle)=>{const star = Star.add( x, y,this.color, angle, Math.pow(Math.random(),0.45)* speed,// 非线性速度分布this.starLife + Math.random()*this.starLife *this.starLifeVariation ); star.onDeath = onDeath;// 设置死亡效果});// 3. 播放爆炸音效const soundSize = Math.min(2,this.size /200); FireworkSound.playBurst(soundSize);}}

烟花类型对照表:

类型中文名特点视觉效果
Crysanthemum菊花经典球形爆炸,密集粒子大型圆形散开
Palm棕榈垂直拖尾,像棕榈树向下垂落
Ring圆环环形爆炸空心圆环
Crossette十字爆炸后分裂成四个小星星二次爆炸
Floral花簇小型二次爆炸多层绽放
Crackle噼啪金色火花,噼啪声金色闪烁
Willow垂柳长时间下坠的火花长尾下垂
Falling Leaves落叶飘落的金色粒子缓慢飘落
Horse Tail马尾水平拖尾横向展开
4. Star 星星粒子
const Star ={drawWidth:3,airDrag:0.98,airDragHeavy:0.992,active:createParticleCollection(),// 按颜色分组的活跃粒子_pool:[],// 对象池,复用粒子对象add(x, y, color, angle, speed, life, speedOffX, speedOffY){// 从池中获取或创建新对象const instance =this._pool.pop()||{}; instance.x = x; instance.y = y; instance.prevX = x;// 上一帧位置(用于绘制轨迹) instance.prevY = y; instance.color = color; instance.speedX = Math.sin(angle)* speed +(speedOffX ||0); instance.speedY = Math.cos(angle)* speed +(speedOffY ||0); instance.life = life; instance.sparkFreq =0;// 火花频率this.active[color].push(instance);return instance;},returnInstance(instance){ instance.onDeath && instance.onDeath(instance); instance.onDeath =null;this._pool.push(instance);// 回收到池中}};

对象池模式优势:

  • 避免频繁创建/销毁对象
  • 减少垃圾回收(GC)压力
  • 提高大量粒子时的性能
5. Spark 火花粒子
const Spark ={drawWidth:0.75,airDrag:0.9,active:createParticleCollection(),_pool:[],add(x, y, color, angle, speed, life){const instance =this._pool.pop()||{}; instance.x = x; instance.y = y; instance.prevX = x; instance.prevY = y; instance.color = color; instance.speedX = Math.sin(angle)* speed; instance.speedY = Math.cos(angle)* speed; instance.life = life;this.active[color].push(instance);return instance;}};

Star 与 Spark 的区别:

特性StarSpark
大小3px0.75px
空气阻力0.980.9
用途主要烟花粒子闪光效果
寿命较长较短
6. 渲染循环
functionupdate(frameTime, lag){if(!canInteract())return;const timeStep = frameTime * simSpeed;const speed = simSpeed * lag;// 1. 更新全局状态(自动发射等)updateGlobals(timeStep, lag);// 2. 计算物理参数const starDrag =1-(1- Star.airDrag)* speed;// 空气阻力系数const sparkDrag =1-(1- Spark.airDrag)* speed;const gAcc = timeStep /1000*GRAVITY;// 重力加速度// 3. 更新所有粒子COLOR_CODES_W_INVIS.forEach(color=>{// 更新星星 Star.active[color].forEach((star, i, stars)=>{ star.life -= timeStep;if(star.life <=0){ stars.splice(i,1); Star.returnInstance(star);}else{// 保存上一帧位置 star.prevX = star.x; star.prevY = star.y;// 物理更新 star.x += star.speedX * speed; star.y += star.speedY * speed; star.speedX *= starDrag; star.speedY *= starDrag; star.speedY += gAcc;// 重力// 旋转效果if(star.spinRadius){ star.spinAngle += star.spinSpeed * speed; star.x += Math.sin(star.spinAngle)* star.spinRadius * speed; star.y += Math.cos(star.spinAngle)* star.spinRadius * speed;}// 火花效果if(star.sparkFreq){ star.sparkTimer -= timeStep;while(star.sparkTimer <0){ star.sparkTimer += star.sparkFreq; Spark.add(star.x, star.y, star.sparkColor,...);}}}});// 更新火花 Spark.active[color].forEach((spark, i, sparks)=>{// 类似星星的物理更新...});});// 4. 渲染render(speed);}
7. 渲染函数
functionrender(speed){const{ dpr, width, height }= mainStage;const trailsCtx = trailsStage.ctx;const mainCtx = mainStage.ctx;// 1. 更新天空颜色colorSky(speed);// 2. 设置变换 trailsCtx.scale(dpr, dpr); mainCtx.scale(dpr, dpr);// 3. 绘制拖尾效果(渐变黑色覆盖) trailsCtx.globalCompositeOperation ='source-over'; trailsCtx.fillStyle =`rgba(0, 0, 0, ${longExposure ?0.0025:0.1* speed})`; trailsCtx.fillRect(0,0, width, height);// 4. 设置混合模式 trailsCtx.globalCompositeOperation ='lighten';// 5. 清空主画布 mainCtx.clearRect(0,0, width, height);// 6. 绘制爆炸闪光while(BurstFlash.active.length){const bf = BurstFlash.active.pop();const gradient = trailsCtx.createRadialGradient(bf.x, bf.y,0, bf.x, bf.y, bf.radius); gradient.addColorStop(0.05,'white'); gradient.addColorStop(0.25,'rgba(255, 160, 20, 0.2)'); gradient.addColorStop(1,'rgba(255, 160, 20, 0)'); trailsCtx.fillStyle = gradient; trailsCtx.fillRect(bf.x - bf.radius, bf.y - bf.radius, bf.radius *2, bf.radius *2);}// 7. 绘制星星轨迹 trailsCtx.lineWidth = Star.drawWidth; trailsCtx.lineCap ='round';COLOR_CODES.forEach(color=>{const stars = Star.active[color]; trailsCtx.strokeStyle = color; trailsCtx.beginPath(); stars.forEach(star=>{ trailsCtx.moveTo(star.x, star.y); trailsCtx.lineTo(star.prevX, star.prevY);}); trailsCtx.stroke();});// 8. 绘制火花 trailsCtx.lineWidth = Spark.drawWidth; trailsCtx.lineCap ='butt';// 类似星星的绘制...// 9. 绘制速度条if(speedBarOpacity){ mainCtx.globalAlpha = speedBarOpacity; mainCtx.fillStyle =COLOR.Blue; mainCtx.fillRect(0, height -6, width * simSpeed,6); mainCtx.globalAlpha =1;}// 10. 重置变换 trailsCtx.resetTransform(); mainCtx.resetTransform();}
8. 天空颜色计算
const currentSkyColor ={r:0,g:0,b:0};const targetSkyColor ={r:0,g:0,b:0};functioncolorSky(speed){const maxSkySaturation =30;// 最大天空饱和度const maxStarCount =500;// 达到最大亮度所需的星星数量let totalStarCount =0; targetSkyColor.r =0; targetSkyColor.g =0; targetSkyColor.b =0;// 累计所有颜色的亮度COLOR_CODES.forEach(color=>{const tuple =COLOR_TUPLES[color];const count = Star.active[color].length; totalStarCount += count; targetSkyColor.r += tuple.r * count; targetSkyColor.g += tuple.g * count; targetSkyColor.b += tuple.b * count;});// 非线性映射,模拟人眼感知const intensity = Math.pow(Math.min(1, totalStarCount / maxStarCount),0.3);// 归一化并应用强度const maxColorComponent = Math.max(1, targetSkyColor.r, targetSkyColor.g, targetSkyColor.b); targetSkyColor.r = targetSkyColor.r / maxColorComponent * maxSkySaturation * intensity; targetSkyColor.g = targetSkyColor.g / maxColorComponent * maxSkySaturation * intensity; targetSkyColor.b = targetSkyColor.b / maxColorComponent * maxSkySaturation * intensity;// 平滑过渡const colorChange =10; currentSkyColor.r +=(targetSkyColor.r - currentSkyColor.r)/ colorChange * speed; currentSkyColor.g +=(targetSkyColor.g - currentSkyColor.g)/ colorChange * speed; currentSkyColor.b +=(targetSkyColor.b - currentSkyColor.b)/ colorChange * speed;// 应用到背景 appNodes.canvasContainer.style.backgroundColor =`rgb(${currentSkyColor.r |0}, ${currentSkyColor.g |0}, ${currentSkyColor.b |0})`;}

五、用户交互

1. 点击发射
functionhandlePointerStart(event){ activePointerCount++; FireworkSound.unlock();// iOS 音频解锁 FireworkSound.resume();const btnSize =44;// 点击顶部按钮区域if(event.y < btnSize){if(event.x < btnSize){togglePause();return;}if(event.x > mainStage.width/2- btnSize/2&& event.x < mainStage.width/2+ btnSize/2){toggleLongExposure();return;}if(event.x > mainStage.width - btnSize){toggleMenu();return;}}// 点击画布发射烟花if(!canInteract())return;if(updateSpeedFromEvent(event)){ isUpdatingSpeed =true;}elseif(event.onCanvas){launchShellFromConfig(event);}}
2. 键盘快捷键
functionhandleKeydown(event){if(event.keyCode ===80)togglePause();// P 键 - 暂停if(event.keyCode ===79)toggleMenu();// O 键 - 菜单if(event.keyCode ===27)toggleMenu(false);// ESC 键 - 关闭菜单}
3. 自动发射序列
functionstartSequence(){if(isFirstSeq){ isFirstSeq =false;const shell =newShell(crysanthemumShell(shellSizeSelector())); shell.launch(0.5,0.5);// 首发居中return2400;}if(finaleSelector()){// 终场模式:快速连续发射seqRandomShell();if(currentFinaleCount < finaleCount){ currentFinaleCount++;return170;// 170ms 间隔}else{ currentFinaleCount =0;return6000;// 暂停 6 秒}}// 随机选择发射模式const rand = Math.random();if(rand <0.2)returnseqSmallBarrage();// 小型连发if(rand <0.6)returnseqRandomShell();// 单发if(rand <0.8)returnseqTwoRandom();// 双发returnseqTriple();// 三发}

六、性能优化要点

优化技术说明效果
对象池复用 Star/Spark 对象减少 GC 压力
颜色分组按颜色分组批量渲染减少 Canvas 状态切换
双缓冲trails-canvas 保留历史轨迹实现拖尾效果
requestAnimationFrame与屏幕刷新同步流畅动画
空气阻力模拟粒子速度衰减自然消散效果
设备像素比适配scale(dpr, dpr)高清显示

七、iOS 适配

1. Meta 标签优化
<!-- 视口适配刘海屏 --><metaname="viewport"content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover"><!-- iOS Web App 支持 --><metaname="apple-mobile-web-app-capable"content="yes"><metaname="apple-mobile-web-app-status-bar-style"content="black-translucent"><metaname="apple-mobile-web-app-title"content="烟花盛宴"><!-- 禁用电话号码识别 --><metaname="format-detection"content="telephone=no"><!-- PWA Manifest --><linkrel="manifest"href="data:application/json;base64,...">
2. CSS 触摸优化
*{-webkit-tap-highlight-color: transparent;/* 移除点击高亮 */-webkit-touch-callout: none;/* 禁用长按菜单 */-webkit-user-select: none;/* 禁止选择文字 */touch-action: manipulation;/* 禁用双击缩放 */}body{overscroll-behavior: none;/* 禁用橡皮筋效果 */padding:env(safe-area-inset-*);/* 适配安全区域 */}
3. Web Audio 解锁
unlock(){if(this.isUnlocked)returntrue;// iOS 要求:必须在用户交互中创建并播放音频if(this.ctx.state ==='suspended'){this.ctx.resume();}// 播放静音缓冲区解锁音频const buffer =this.ctx.createBuffer(1,1,22050);const source =this.ctx.createBufferSource(); source.buffer = buffer; source.connect(this.ctx.destination); source.start(0);this.isUnlocked =true;}
4. 手势防护
// 禁用 iOS 缩放手势 document.addEventListener('gesturestart',(e)=> e.preventDefault()); document.addEventListener('gesturechange',(e)=> e.preventDefault()); document.addEventListener('gestureend',(e)=> e.preventDefault());// 防止双击缩放let lastTouchEnd =0; document.addEventListener('touchend',(e)=>{const now = Date.now();if(now - lastTouchEnd <=300){ e.preventDefault();} lastTouchEnd = now;});
5. iOS 支持功能表
功能状态说明
添加到主屏幕✅支持全屏运行
声音播放✅用户交互后解锁
刘海屏适配✅安全区域 padding
禁用缩放✅手势防护
禁用橡皮筋效果✅overscroll-behavior
触摸响应✅Pointer Events

八、文件依赖

外部库
├── fscreen@1.0.1.js - 全屏 API 兼容库 ├── Stage@0.1.4.js - Canvas 舞台管理 └── MyMath.js - 数学工具函数 
本地文件
└── style.css - 额外样式(可选) 

总结

这是一个功能完整的交互式烟花动画网页,主要特点:

  1. 视觉效果:双层 Canvas 实现拖尾效果,混合模式增强亮度
  2. 音效系统:8 种不同风格的音效,Web Audio API 实时生成
  3. 物理模拟:重力、空气阻力、粒子生命周期
  4. 状态管理:发布-订阅模式,localStorage 持久化
  5. 性能优化:对象池、颜色分组、requestAnimationFrame
  6. 跨平台:完整的 iOS/移动端适配

目录

  1. 目录
  2. 一、整体架构
  3. 二、HTML 结构部分
  4. 1\. 头部元信息
  5. 2\. iOS PWA 支持
  6. 3\. SVG 图标定义
  7. 4\. Canvas 画布容器
  8. 5\. 控制面板
  9. 6\. 设置菜单
  10. 7\. 首次交互提示(iOS 适配)
  11. 三、CSS 样式部分
  12. 1\. 全局样式与触摸优化
  13. 2\. 混合模式
  14. 3\. 动画过渡
  15. 4\. 音频提示动画
  16. 四、JavaScript 核心模块
  17. 1\. FireworkSound 音效模块
  18. 2\. Store 状态管理
  19. 3\. Shell 烟花类
  20. 4\. Star 星星粒子
  21. 5\. Spark 火花粒子
  22. 6\. 渲染循环
  23. 7\. 渲染函数
  24. 8\. 天空颜色计算
  25. 五、用户交互
  26. 1\. 点击发射
  27. 2\. 键盘快捷键
  28. 3\. 自动发射序列
  29. 六、性能优化要点
  30. 七、iOS 适配
  31. 1\. Meta 标签优化
  32. 2\. CSS 触摸优化
  33. 3\. Web Audio 解锁
  34. 4\. 手势防护
  35. 5\. iOS 支持功能表
  36. 八、文件依赖
  37. 外部库
  38. 本地文件
  39. 总结

更多推荐文章

查看全部
  • Stable Diffusion 显存优化方案与自动释放扩展使用指南
  • 算法基础:一维前缀和与最大子段和实战
  • OpenClaw 自托管 AI 网关部署实战指南
  • Python 基于大数据的校园美食推荐系统设计
  • 多分类Logit回归原理及分析结果指标解读
  • Uptime Kuma 部署安装运维指南
  • 大模型训练技术架构、并行策略与优化方案详解
  • Mac 本地离线 AI 绘画实战:Mochi Diffusion 部署指南
  • C++ 标准库 count 用法详解
  • 线性 DP 经典四题详解:台阶、子段和、传球与乌龟棋
  • 豆包 Seedream 4.0 多图融合与主体一致性技术解析
  • Hymba:融合注意力与 SSM 头的新型语言模型架构
  • 蓝桥杯C/C++大学B组省赛真题解析与实战技巧
  • 工业大模型市场图谱:53 个工业大模型梳理
  • JavaScript 运算符与流程控制详解
  • Android ScrollView 滑动实现标题栏渐变背景色
  • 大疆无人机五种反制手段实测:干扰枪与激光武器效果对比
  • 基于 Django 框架和 Python 的社团活动管理微信小程序设计实现
  • GitHub for Visual Studio 安装与协作全流程指南
  • AI 产品经理面试全攻略

相关免费在线工具

  • curl 转代码

    解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online