<div id="screen">
  <canvas id="canvas"></canvas>
  <button id="fire">20発 打ち上げ</button>
</div>
body {
  margin: 0;
  padding: 0;
  overflow: hidden;
  box-sizing: border-box;
}
#screen {
  position: relative;
  width: 100%;
  height: auto;
  margin: 0;
  background-color: black;
}
#canvas {
  width: 100%;
  height: auto;
}
#fire {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 20px;
  display: block;
  width: 200px;
  margin: 24px auto;
  padding: 4px 0;
  font-size: 16px;
  line-height: 1.5em;
  color: black;
  background-color: white;
  border: none;
  border-radius: 4px;
}
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

// パーティクルオブジェクト
class Particle {
  constructor(x, y, color) {
    this.x = x;
    this.y = y;
    this.color = color;
    this.radius = 2; // パーティクルの半径
    
    // パーティクルの速度
    const speed = Math.random() * 2 + 1; // 速度の大きさをランダムに決定
    const angle = Math.random() * Math.PI * 2; // 速度の方向をランダムに決定
    this.speed = { x: Math.cos(angle) * speed, y: Math.sin(angle) * speed };
    
    this.gravity = 0.02; // パーティクルが落ちる速度
    this.opacity = 1; // パーティクルの透明度
  }

  // パーティクルを描画するメソッド
  draw() {
    ctx.beginPath();
    ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
    ctx.save();
    ctx.globalAlpha = this.opacity;
    ctx.fillStyle = this.color;
    ctx.fill();
    ctx.restore();
    ctx.closePath();
  }

  // パーティクルの移動
  update() {
  this.speed.y += this.gravity; // 重力を加える
  this.x += this.speed.x; // X方向に速度を加える
  this.y += this.speed.y; // Y方向に速度を加える
  this.opacity -= 0.01; // 徐々に透明にする
  if (this.opacity < 0) { // 透明度が0より小さくなったら
    this.opacity = 0; // 透明度を0に設定
  }
  this.draw(); // パーティクルを描画
}

  // パーティクルが完全に透明になったかどうかを確認するメソッド
  get isDead() {
    return this.opacity <= 0;
  }
}

// 花火を作成する関数
function createFirework(x, y) {
  const fireworkColors = ['#fff469', '#ffec47', '#ffe449']; // 花火の色 Na燃焼
  const particles = []; // パーティクルを格納する配列

  // 花火の爆発パーティクルを生成
  for (let i = 0; i < 60; i++) {
    const color = fireworkColors[Math.floor(Math.random() * fireworkColors.length)];
    const particle = new Particle(x, y, color);
    particles.push(particle);
  }

  // アニメーションフレームで花火のパーティクルをアップデートし、描画
  function animate() {
    const animation = requestAnimationFrame(animate);
    ctx.fillStyle = 'rgba(0, 0, 0, .1)';
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    particles.forEach((particle, index) => {
      if (!particle.isDead) {
        particle.update();
      } else {
        particles.splice(index, 1);
      }
    });
    if (particles.length === 0) {
      cancelAnimationFrame(animation);
    }
  }

  animate();
}

// ボタン要素を取得
const fireButton = document.getElementById('fire');

// ボタンがクリックされたときのイベントリスナーを追加
fireButton.addEventListener('click', () => {
  let count = 0; // 打ち上げた花火の数をカウント

  // 花火を打ち上げる関数
  function launchFirework() {
    if (count < 20) { // 20発未満の場合
      const randomX = Math.random() * canvas.width;
      const randomY = Math.random() * canvas.height;
      createFirework(randomX, randomY);
      count++; // カウントを増やす
      setTimeout(launchFirework, 1000); // 1秒後に次の花火を打ち上げる
    }
  }

  // 最初の花火を打ち上げる
  launchFirework();
});

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.