尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

用300行HTML+JavaScript实现canvas烟花粒子动画

用300行HTML+JavaScript实现canvas烟花粒子动画 1. 项目概述300行HTML代码能做出一场什么样的烟花先说结论用300行左右的HTML CSS JavaScript完全可以在浏览器里实现一场效果相当不错的烟花动画。这件事本身不算什么新奇玩法很多人写过年份烟花、生日烟花、表白烟花但恰恰是这种“随手能做的小项目”最能体现前端基础功的扎实程度。我做这个项目的初衷很简单年底想给页面加一点氛围感又不想引第三方库、不想上Canvas重型方案最好单文件、零依赖双击就能跑。于是就把目标定在300行代码以内纯手写一套烟花粒子系统。结果做完一数287行算上注释和空行正好卡在300以内。这个项目适合谁来参考如果你刚学完HTML、CSS、JavaScript基础想找一个能串联DOM操作、动画循环、面向对象思路的实战练手这个项目刚刚好。如果你已经有一定前端经验也可以看看我在粒子管理、性能优化和兼容性处理上的一些取舍。最终效果不复杂但也不寒酸夜空背景下烟花从底部升空到达指定高度炸开炸出几十到上百颗粒子粒子有颜色渐变、有拖尾、有重力下落、有自然消散整个生命周期结束之后自动回收再继续放下一发。下面我把整个拆解过程、核心代码设计、实操踩坑都写出来你可以直接照着做也可以在这个基础上改成自己的玩法。我会尽量把每一个关键决策背后的原因讲清楚而不是直接丢一段代码让你复制完事。2. 动画设计思路为什么用粒子系统而不是纯CSS动画2.1 烟花动画的本质是粒子生命周期管理很多人第一反应是烟花不就是一堆div加上CSS动画吗确实可以做网上也有很多纯CSS的烟花效果但那种方案基本只能做“固定形态”的爆炸预先设计好轨迹、延迟、颜色然后让CSS去播。它的问题是每一朵烟花的形态是写死的很难做随机变化而且一个烟花几十个粒子每个粒子都要单独写CSS动画规则代码量和维护成本会迅速膨胀。换个思路用JavaScript驱动粒子运动本质上是做一个微型粒子系统。所谓粒子系统你可以把它理解成一个“粒子工厂”不断生成粒子、更新粒子状态、绘制粒子、销毁粒子。每一发烟花就是一次“生成→运动→消亡”的完整生命周期。这个思路的好处是所有烟花的爆炸形态、粒子数量、颜色、速度都可以用参数控制随机性交给Math.random()即可完全不受CSS动画数量的限制。用生活类比来说纯CSS方案像是一个精心编排过的舞蹈节目每一个动作都是排练好的粒子系统方案则像是一群有简单行为规则的演员你只给他们设定“从某个点出发、带有初速度、受重力影响、逐渐变透明”他们自己就能演出一场每次都不一样的烟花秀。2.2 为了让动画“像烟花”需要满足哪几个物理要素真实烟花的视觉特征拆解下来其实是几个物理要素的组合缺一个都不“像”弹道上升阶段烟花不是直接在空中出现的它有一个发射过程。火箭从地面拖着一条光尾升到空中速度是越来越慢的因为初始动能克服重力做功。这个阶段我用一个简单的物理模拟每帧速度减去一个固定重力值直到速度耗尽在最高点附近引爆。爆炸粒子群真实烟花炸开之后粒子是沿各个方向飞散的。我用“一圈粒子的均匀分布 少量随机偏移”来模拟这个效果。均匀分布保证整体呈圆形膨胀随机偏移则让边缘不那么整齐看起来更自然。粒子拖尾烟花粒子在飞行时会留下光迹因为人的视觉有残像效应。我用“上一个位置画一条半透明短线的连线”来模拟而不是真的去记录几十帧的历史位置。这个做法简单得多视觉上也够用。重力下落与阻力爆炸之后粒子不会无限飞远它们受重力影响下落同时受到空气阻力。我在每帧更新里固定让vy增加一个重力加速度同时给速度乘以一个略小于1的阻尼系数比如0.98这样粒子会慢慢减速、掉头、落地。消散机制粒子是有寿命的不能一直留在屏幕上。我给每个粒子设置一个life属性从出生开始每帧递减当寿命耗尽时粒子透明度逐渐归零并从数组中移除。这一步是整个系统的核心没有销毁机制的粒子系统跑几分钟后内存和DOM节点就会爆炸。2.3 为什么用requestAnimationFrame而不是setInterval动画循环用requestAnimationFrame是前端基础常识但很多初学者会图省事用setInterval(fn, 16)来做。这里我说一下为什么必须用requestAnimationFrame。首先requestAnimationFrame是浏览器原生的帧回调机制它的执行频率和屏幕刷新率同步通常是60fps高刷屏上可能是120fps。如果屏幕是120Hz你用setInterval固定16毫秒执行一次要么动画显得卡要么白白消耗CPU。而requestAnimationFrame会自动适配刷新率这是它最直接的优势。其次requestAnimationFrame在页面切到后台时会自动暂停不会继续白白消耗资源。而setInterval在后台标签页里依然会照常执行对电池和CPU都不友好。还有一个细节是时间参数requestAnimationFrame回调会自动传入一个时间戳毫秒级在做基于时间的动画时非常方便。比如让粒子颜色随生命周期渐变可以直接拿生命周期比例来算而不需要自己维护一个时钟。3. 核心代码设计与实现从空HTML文件到完整烟花动画3.1 整体文件结构一个HTML文件搞定所有事我自己做这种小项目除非有特殊需求否则一定坚持单文件方案。一个index.htmlCSS塞在
返回列表