用 HTML 实现新春烟花的详细笔记

新年的钟声即将敲响,绚丽的烟花在夜空中绽放,将节日氛围拉满。想不想把这美好的一幕搬到你的网页上,下面跟着小编用 HTML 和 JavaScript 打造出专属的新春烟花特效吧,制造属于IT的浪漫吧!朋友们

一、准备舞台:搭建 HTML 基础框架

就像举办一场烟花秀需要一个空旷的场地,我们的新春烟花特效也需要一个 "舞台",这就是 HTML 页面。先看下面这段代码,它就是我们搭建的 "舞台" 基础:

html 复制代码
<!DOCTYPE html>

<html lang="zh-CN">

<head>

&#x20;<meta charset="UTF-8">

&#x20;<meta name="viewport" content="width=device-width, initial-scale=1.0">

&#x20;<title>新春烟花🎆</title>

&#x20;<style>

&#x20;   body {

&#x20;     margin: 0;

&#x20;     overflow: hidden;

&#x20;     background: #000;

&#x20;   }

&#x20;   canvas {

&#x20;     display: block;

&#x20;   }

&#x20; </style>

</head>

<body>

<canvas id="fireworksCanvas"></canvas>

<script>

&#x20; // 这里开始写JavaScript代码

</script>

</body>

</html>

HTML 基本结构<!DOCTYPE html>声明这是一个 HTML5 文档。<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;去掉了页面默认的边距,让页面更紧凑;overflow: hidden;隐藏了页面的滚动条,因为我们的烟花秀不需要滚动条来打扰;background: #000;把背景设置成黑色,就像夜晚的天空,这样烟花会更醒目。canvas部分,display: block;<canvas>元素以块级元素显示,为后面绘制烟花做好准备。

搭建画布<body>标签里的<canvas id="fireworksCanvas"></canvas>创建了一个画布,idfireworksCanvas,这就像是我们画画用的白纸,之后的烟花都会在这个画布上绘制。<script>标签是我们放 JavaScript 代码的地方,这里先空着,等下再 "大展身手"。

二、注入灵魂:编写 JavaScript 代码

HTML 搭建好舞台后,接下来就要用 JavaScript 给这个舞台注入灵魂,让烟花在上面绽放。

1. 获取画布并设置尺寸

html 复制代码
const canvas = document.getElementById("fireworksCanvas");

const ctx = canvas.getContext("2d");

canvas.width = window.innerWidth;

canvas.height = window.innerHeight;

这几行代码就像找到了我们刚刚搭建的画布,并根据浏览器窗口的大小调整画布的尺寸,这样不管窗口怎么变化,烟花都能完美铺满整个屏幕。document.getElementById("fireworksCanvas")通过id找到了<canvas>元素,canvas.getContext("2d")获取了二维绘图上下文,就像是拿到了一支画笔,准备在画布上作画。canvas.widthcanvas.height设置了画布的宽和高,让画布和浏览器窗口一样大。

2. 定义烟花类

html 复制代码
class Firework {

&#x20; constructor(x, y, color, velocity, size) {

&#x20;   this.x = x;

&#x20;   this.y = y;

&#x20;   this.color = color;

&#x20;   this.velocity = velocity;

&#x20;   this.size = size;

&#x20;   this.opacity = 1;

&#x20; }

&#x20; draw() {

&#x20;   ctx.save();

&#x20;   ctx.globalAlpha = this.opacity;

&#x20;   ctx.beginPath();

&#x20;   ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);

&#x20;   ctx.fillStyle = this.color;

&#x20;   ctx.fill();

&#x20;   ctx.restore();

&#x20; }

&#x20; update() {

&#x20;   this.x += this.velocity.x;

&#x20;   this.y += this.velocity.y;

&#x20;   this.velocity.y += gravity;

&#x20;   this.opacity -= 0.01;

&#x20; }

}

Firework类就像是烟花的 "制造工厂",每个烟花都由这个类创建。constructor是构造函数,就像工厂的生产线,创建烟花时会设置烟花的初始位置(x, y)、颜色color、速度velocity、大小size和透明度opacitydraw方法是烟花的 "绘制蓝图",它告诉计算机怎么在画布上画出烟花,通过设置透明度、绘制圆形并填充颜色来实现。update方法则是烟花的 "运动指南",它让烟花按照一定的速度和重力移动,并且随着时间推移逐渐变淡。

3. 创建烟花

html 复制代码
function createFirework(x, y) {

&#x20; const colors = ["#FF5733", "#FFBD33", "#33FF57", "#33D4FF", "#AF33FF", "#FF33A6"];

&#x20; const particles = [];

&#x20; const particleCount = 100;

&#x20; for (let i = 0; i < particleCount; i++) {

&#x20;   constangle = Math.random() * Math.PI * 2;

&#x20;   constspeed = Math.random() * 4 + 2;

&#x20;   constvelocity = {x:Math.cos(angle) * speed, y:Math.sin(angle) * speed };

&#x20;   constsize = Math.random() * 2 + 1;

&#x20;   constcolor = colors[Math.floor(Math.random() * colors.length)];

&#x20;   particles.push(newFirework(x, y, color, velocity, size));

&#x20; }

&#x20; fireworks.push(...particles);

}

createFirework函数就像是烟花的 "发射按钮",它会在指定位置(x, y)创建一个烟花。这里定义了一个颜色数组colors,里面存放了各种绚丽的颜色,就像一个颜料盒。通过循环particleCount次,每次随机生成角度、速度、大小和颜色,创建出不同的烟花粒子,最后把这些粒子组成一个烟花并添加到fireworks数组里。

4. 绘制文字

html 复制代码
function drawMessage() {

&#x20; if (message && messageOpacity > 0) {

&#x20;   ctx.save();

&#x20;   ctx.globalAlpha = messageOpacity;

&#x20;   ctx.fillStyle = "gold";

&#x20;   ctx.font = "bold 48px 微软雅黑, SimHei, Arial, sans-serif";

&#x20;   ctx.textAlign = "center";

&#x20;   // 将文字放到画布的正中央

&#x20;   ctx.fillText(message, canvas.width / 2, canvas.height / 2);

&#x20;   ctx.restore();

&#x20; }

}

drawMessage函数就像是在烟花秀现场挂了一个横幅,它会在画布上绘制文字。当message存在且文字透明度messageOpacity大于 0 时,设置文字的颜色、字体、对齐方式,然后把文字绘制在画布的正中央。

5. 动画循环

html 复制代码
function animate() {

&#x20; ctx.fillStyle = "rgba(0, 0, 0, 0.2)";

&#x20; ctx.fillRect(0, 0, canvas.width, canvas.height);

&#x20; fireworks.forEach((firework, index) => {

&#x20;   if (firework.opacity <= 0) {

&#x20;     fireworks.splice(index, 1);

&#x20;   } else {

&#x20;     firework.update();

&#x20;     firework.draw();

&#x20;   }

&#x20; });

&#x20; drawMessage();

&#x20; if (messageOpacity > 0) {

&#x20;   messageOpacity -= 0.01; // 文字逐渐淡出

&#x20; }

&#x20; requestAnimationFrame(animate);

}

animate函数是整个烟花秀的 "总指挥",它会不断地重复执行,让烟花持续绽放。首先,用一个半透明的黑色矩形覆盖画布,就像清理舞台,准备下一次表演。然后遍历fireworks数组,对每个烟花进行更新和绘制,如果烟花的透明度小于等于 0,就把它从数组中移除。接着调用drawMessage函数绘制文字,并且让文字的透明度逐渐降低,实现文字淡出效果。最后,通过requestAnimationFrame(animate)请求浏览器在下一次重绘之前调用animate函数,形成动画循环。

6. 触发烟花和文字显示

html 复制代码
// 初始加载时,立即触发一次烟花效果和文字显示

const initialFirework = () => {

&#x20; const x = Math.random() * canvas.width;

&#x20; const y = Math.random() * canvas.height;

&#x20; createFirework(x, y);

&#x20; // 显示"新春快乐"

&#x20; message = "IT小本本   祝  大家新春快乐!";

&#x20; messageOpacity = 1; // 重置文字透明度

&#x20; messageTimer = 0; // 重置计时器

}

// 页面加载时,立即执行一次效果

initialFirework();

// 每隔1秒触发一次烟花效果和文字显示

setInterval(() => {

&#x20; const x = Math.random() * canvas.width;

&#x20; const y = Math.random() * canvas.height;

&#x20; createFirework(x, y);

&#x20; // 显示"新春快乐"

&#x20; message = "IT小本本   祝  大家新春快乐!";

&#x20; messageOpacity = 1; // 重置文字透明度

&#x20; messageTimer = 0; // 重置计时器

}, 10); // 每秒执行一次

window.addEventListener("resize", () => {

&#x20; canvas.width = window.innerWidth;

&#x20; canvas.height = window.innerHeight;

});

animate();

这部分代码就像是烟花秀的 "开场哨" 和 "定时炸弹"。initialFirework函数在页面初始加载时被调用,随机在画布上的某个位置创建一个烟花,并显示 " 祝 大家新春快乐!" 的文字。setInterval函数就像一个定时闹钟,每隔 1 秒(这里设置为 10 毫秒,实际测试中可根据需要调整,可能设置 1000 毫秒即 1 秒效果更好)就会触发一次,随机创建一个烟花并显示文字。window.addEventListener("resize", () => {... })监听窗口大小变化,当窗口大小改变时,重新设置画布的尺寸,保证烟花始终能完美显示。最后调用animate函数,运行烟花秀。

还没学会的同学,复制下面代码,然后保存为.html文件,浏览器打开就可以看到效果了!!

完整详细代码

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">

<head>
  <meta charset="UTF-8">
  
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  
</style>
  <title>新春烟花🎆</title>
  <style>
    body {
      margin: 0;
      overflow: hidden;
      background: #000;
    }
    canvas {
      display: block;
    }
  </style>
</head>
<body>
<canvas id="fireworksCanvas"></canvas>

<script>
  const canvas = document.getElementById("fireworksCanvas");
  const ctx = canvas.getContext("2d");

  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;

  const fireworks = [];
  const gravity = 0.05;
  let message = null; // 当前文字信息
  let messageOpacity = 0; // 文字透明度
  let messageTimer = 0; // 文字显示计时器

  class Firework {
    constructor(x, y, color, velocity, size) {
      this.x = x;
      this.y = y;
      this.color = color;
      this.velocity = velocity;
      this.size = size;
      this.opacity = 1;
    }

    draw() {
      ctx.save();
      ctx.globalAlpha = this.opacity;
      ctx.beginPath();
      ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
      ctx.fillStyle = this.color;
      ctx.fill();
      ctx.restore();
    }

    update() {
      this.x += this.velocity.x;
      this.y += this.velocity.y;
      this.velocity.y += gravity;
      this.opacity -= 0.01;
    }
  }

  function createFirework(x, y) {
    const colors = ["#FF5733", "#FFBD33", "#33FF57", "#33D4FF", "#AF33FF", "#FF33A6"];
    const particles = [];
    const particleCount = 100;

    for (let i = 0; i < particleCount; i++) {
      const angle = Math.random() * Math.PI * 2;
      const speed = Math.random() * 4 + 2;
      const velocity = { x: Math.cos(angle) * speed, y: Math.sin(angle) * speed };
      const size = Math.random() * 2 + 1;
      const color = colors[Math.floor(Math.random() * colors.length)];
      particles.push(new Firework(x, y, color, velocity, size));
    }

    fireworks.push(...particles);
  }

  function drawMessage() {
    if (message && messageOpacity > 0) {
      ctx.save();
      ctx.globalAlpha = messageOpacity;
      ctx.fillStyle = "gold";
      ctx.font = "bold 48px 微软雅黑, SimHei, Arial, sans-serif";
      ctx.textAlign = "center";
      // 将文字放到画布的正中央
      ctx.fillText(message, canvas.width / 2, canvas.height / 2);
      ctx.restore();
    }
  }

  function animate() {
    ctx.fillStyle = "rgba(0, 0, 0, 0.2)";
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    fireworks.forEach((firework, index) => {
      if (firework.opacity <= 0) {
        fireworks.splice(index, 1);
      } else {
        firework.update();
        firework.draw();
      }
    });

    drawMessage();

    if (messageOpacity > 0) {
      messageOpacity -= 0.01; // 文字逐渐淡出
    }

    requestAnimationFrame(animate);
  }

  // 初始加载时,立即触发一次烟花效果和文字显示
  const initialFirework = () => {
    const x = Math.random() * canvas.width;
    const y = Math.random() * canvas.height;
    createFirework(x, y);

    // 显示"新春快乐"
    message = "IT小本本   祝  大家新春快乐!";
    messageOpacity = 1; // 重置文字透明度
    messageTimer = 0; // 重置计时器
  }

  // 页面加载时,立即执行一次效果
  initialFirework();

  // 每隔1秒触发一次烟花效果和文字显示
  setInterval(() => {
    const x = Math.random() * canvas.width;
    const y = Math.random() * canvas.height;
    createFirework(x, y);

    // 显示"新春快乐"
    message = "IT小本本   祝  大家新春快乐!";
    messageOpacity = 1; // 重置文字透明度
    messageTimer = 0; // 重置计时器
  }, 10); // 每秒执行一次

  window.addEventListener("resize", () => {
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
  });

  animate();
</script>
</body>
</html>
相关推荐
╰つ゛木槿1 分钟前
深入探索 Vue 3 Markdown 编辑器:高级功能与实现
前端·vue.js·编辑器
yqcoder20 分钟前
Commander 一款命令行自定义命令依赖
前端·javascript·arcgis·node.js
前端Hardy36 分钟前
HTML&CSS :下雪了
前端·javascript·css·html·交互
醉の虾43 分钟前
VUE3 使用路由守卫函数实现类型服务器端中间件效果
前端·vue.js·中间件
Jackilina_Stone1 小时前
【论文阅读笔记】“万字”关于深度学习的图像和视频阴影检测、去除和生成的综述笔记 | 2024.9.3
论文阅读·人工智能·笔记·深度学习·ai
码上飞扬2 小时前
Vue 3 30天精进之旅:Day 05 - 事件处理
前端·javascript·vue.js
Ronin-Lotus2 小时前
上位机知识篇---CMake
c语言·c++·笔记·学习·跨平台·编译·cmake
火烧屁屁啦2 小时前
【JavaEE进阶】应用分层
java·前端·java-ee
程序员小寒2 小时前
由于请求的竞态问题,前端仔喜提了一个bug
前端·javascript·bug
赵不困888(合作私信)3 小时前
npx和npm 和pnpm的区别
前端·npm·node.js