简单实现烟花自由

文章展示了一个使用HTML5Canvas和JavaScript编写的烟花动画示例。代码创建了Firework类来表示烟花,包括其位置、速度、角度等属性,并模拟了烟花爆炸后粒子散开的效果。粒子类Particle处理了颜色、摩擦力和重力等物理特性。整个动画通过setInterval定时创建和更新烟花,使用requestAnimationFrame平滑渲染。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Fireworks</title>
    <style>
      html, body {
        width: 100%;
        height: 100%;
        margin: 0;
        padding: 0;
        background-color: black;
        overflow: hidden;
      }
      canvas {
        display: block;
        margin: auto;
      }
    </style>
  </head>
  <body>
    <canvas id="canvas"></canvas>
    <script>
      var canvas = document.getElementById("canvas");
      var ctx = canvas.getContext("2d");

      var width = window.innerWidth;
      var height = window.innerHeight;
      canvas.width = width;
      canvas.height = height;
      
      
      // 烟花的构造函数
      function Firework(x, y) {
        this.x = x;
        this.y = y;
        this.size = 2;
        var random = Math.random();
        this.speed = random * 4 + 8;
        this.angle = 1.25;
        this.vx = Math.cos(this.angle) * this.speed;
        this.vy = Math.sin(this.angle) * this.speed;
        this.gravity = 0.1;
        this.opacity = 1;
        this.particles = [];
        this.isExploded = false;
      }

      Firework.prototype.update = function() {
        if (!this.isExploded) {
          this.x += this.vx;
          this.y -= this.vy + this.gravity;
          if (this.y < height * 0.3) {
            this.explode();
          }
        } else {
          this.particles.forEach(function(particle) {
            particle.vx *= particle.friction;
            particle.vy *= particle.friction;
            particle.vy += particle.gravity;
            particle.x += particle.vx;
            particle.y += particle.vy;
            particle.opacity -= 0.01;
          });
          this.particles = this.particles.filter(function(particle) {
            return particle.opacity > 0;
          });
          if (this.particles.length === 0) {
            this.isExploded = false;
          }
        }
      };

      Firework.prototype.draw = function() {
        if (!this.isExploded) {
          ctx.beginPath();
          //ctx.fillStyle = this.color;
          ctx.globalAlpha = this.opacity;
          ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2, false);
          ctx.closePath();
          ctx.fill();
        } else {
          this.particles.forEach(function(particle) {
            ctx.beginPath();
            ctx.fillStyle = particle.color;
            ctx.globalAlpha = particle.opacity;
            ctx.arc(particle.x, particle.y, particle.size, 0, Math.PI * 2, false);
            ctx.closePath();
            ctx.fill();
          });
        }
      };

      Firework.prototype.explode = function() {
        for (var i = 0; i < 50; i++) {
          var particle = new Particle(this.x, this.y);
          this.particles.push(particle);
        }
        this.isExploded = true;
      };
      
      // 烟花颜色数组
      var colors = ["#FF4136", "#0074D9", "#2ECC40", "#FFDC00", "#7FDBFF", "#FF851B", "#B10DC9"];
      // 粒子的构造函数
      function Particle(x, y) {
        this.x = x;
        this.y = y;
        this.color = colors[Math.floor(Math.random() * colors.length)];
        this.size = 3;
        this.speed = Math.random() * 4 + 2;
        this.angle = Math.random() * Math.PI * 2;
        this.vx = Math.cos(this.angle) * this.speed;
        this.vy = Math.sin(this.angle) * this.speed;
        this.gravity = 0.2;
        this.friction = 0.95;
        this.opacity = 1;
      }

      // 创建烟花并添加到数组中
      var fireworks = [];
      setInterval(function() {
        var x = Math.random() * width;
        var random = Math.random();
        var y = height * (random > 0.8 ? random : 0.85);
        var firework = new Firework(x, y);
        fireworks.push(firework);
      }, 1000);

      // 更新和绘制烟花
      function loop() {
        ctx.fillStyle = "rgba(0, 0, 0, 0.1)";
        ctx.fillRect(0, 0, width, height);
        fireworks.forEach(function(firework, index) {
          firework.update();
          firework.draw();
          if (firework.isExploded && firework.particles.length === 0) {
            fireworks.splice(index, 1);
          }
        });
        requestAnimationFrame(loop);
      }

      loop();
    </script>
  </body>
</html>

 

  • Firework 的构造函数中,增加了 speedanglevxvy 等属性,用来控制烟花的飞行方向和速度。
  • Fireworkupdate 方法中,增加了 isExploded 属性,用来表示烟花是否已经爆炸。如果没有爆炸,烟花会继续向上飞行;如果已经爆炸,烟花就会变成一堆粒子,每个粒子会向各个方向飞行。
  • Fireworkdraw 方法中,增加了对粒子的绘制。
  • Particle 的构造函数中,增加了 friction 属性,用来控制粒子的速度衰减。
  • colors 数组中添加了多个烟花颜色。
  • setInterval 中创建烟花的代码中,将 x 的取值范围改为了整个窗口的宽度,而将 y 的取值范围改为了窗口高度的 80%,这样烟花就会往上飞一段距离后再爆炸。同时,还随机选择一种颜色。
  • loop 函数中,增加了对烟花是否已经爆炸和粒子数量是否为 0 的判断,如果是,就将该烟花从数组中删除,以减少内存占用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值