canvas实现新年烟花效果

209 阅读1分钟

我正在参加「兔了个兔」创意投稿大赛,详情请看:「兔了个兔」创意投稿大赛

一转眼2023年就过去半个月了,还清晰地记得除夕那天晚上的烟花,因此用canvas来写个烟花纪念一下.

实现过程

前期工作我们需要准备好,必须有 <canvas id="fireworks"></canvas>,同时将整个文档的背景色设置为黑色,接下来就是随机数生成每个烟花粒子的数据,同时需要将粒子数据不断地进行变化且重复绘制.

1.获取屏幕的宽度在进行改变屏幕需要重新执行,同时初始化数据

var SCREEN_WIDTH = window.innerWidth,
  SCREEN_HEIGHT = window.innerHeight,
  mousePos = {
    x: 400,
    y: 300
  },
  canvas = document.getElementById("fireworks"),
  context = canvas.getContext("2d"),
  particles = [],
  rockets = [],
  MAX_PARTICLES = 400,
  colorCode = 0;

2.执行我们生产烟花粒子数据的函数和循环渲染的函数.

window.onload = function () {
  canvas.width = SCREEN_WIDTH;
  canvas.height = SCREEN_HEIGHT;
  setInterval(launch, 800);
  setInterval(loop, 1000 / 50);
};

3.生成烟花粒子数据

function launch() {
  launchFrom(mousePos.x);
}

function launchFrom(x) {
  if (rockets.length < 10) {
    var rocket = new Rocket(x);
    rocket.explosionColor = Math.floor((Math.random() * 360) / 10) * 10;
    rocket.vel.y = Math.random() * -3 - 4;
    rocket.vel.x = Math.random() * 6 - 3;
    rocket.size = 8;
    rocket.shrink = 0.999;
    rocket.gravity = 0.01;
    rockets.push(rocket);
  }
}

4.循环改变粒子数据和重复渲染,在每一次执行完之后需要清空整个的canvas画布,使他动态的改变达到烟花火流动的效果.

function loop() {
  // update screen size
  if (SCREEN_WIDTH !== window.innerWidth) {
    canvas.width = SCREEN_WIDTH = window.innerWidth;
  }
  if (SCREEN_HEIGHT !== window.innerHeight) {
    canvas.height = SCREEN_HEIGHT = window.innerHeight;
  }

  // clear canvas
  context.fillStyle = "rgba(0, 0, 0, 0.05)";
  context.fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);

  var existingRockets = [];

  for (var i = 0; i < rockets.length; i++) {
    // update and render
    rockets[i].update();
    rockets[i].render(context);

    // calculate distance with Pythagoras
    var distance = Math.sqrt(
      Math.pow(mousePos.x - rockets[i].pos.x, 2) +
        Math.pow(mousePos.y - rockets[i].pos.y, 2)
    );

    // random chance of 1% if rockets is above the middle
    var randomChance =
      rockets[i].pos.y < (SCREEN_HEIGHT * 2) / 3
        ? Math.random() * 100 <= 1
        : false;

    /* Explosion rules
		 - 80% of screen
		 - going down
		 - close to the mouse
		 - 1% chance of random explosion
		 */
    if (
      rockets[i].pos.y < SCREEN_HEIGHT / 5 ||
      rockets[i].vel.y >= 0 ||
      distance < 50 ||
      randomChance
    ) {
      rockets[i].explode();
    } else {
      existingRockets.push(rockets[i]);
    }
  }

}