← back to Model Arena

data/artifacts/10d3501bd633/qwen3-14b.html

163 lines

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Interactive Fireworks</title>
  <style>
    html, body {
      margin: 0;
      padding: 0;
      overflow: hidden;
      background: black;
      height: 100%;
      width: 100%;
      cursor: pointer;
    }
    canvas {
      display: block;
    }
  </style>
</head>
<body>
<canvas></canvas>
<script>
  const canvas = document.querySelector("canvas");
  const ctx = canvas.getContext("2d");
  let width = canvas.width = window.innerWidth;
  let height = canvas.height = window.innerHeight;
  window.addEventListener("resize", () => {
    width = canvas.width = window.innerWidth;
    height = canvas.height = window.innerHeight;
  });

  class Particle {
    constructor(x, y, color, angle, speed, lifespan) {
      this.x = x;
      this.y = y;
      this.color = color;
      this.angle = angle;
      this.speed = speed;
      this.lifespan = lifespan;
      this.radius = Math.random() * 2 + 1;
      this.gravity = 0.1;
      this.alpha = 1;
    }

    update() {
      this.x += Math.cos(this.angle) * this.speed;
      this.y += Math.sin(this.angle) * this.speed + this.gravity;
      this.speed *= 0.98;
      this.lifespan -= 1;
      this.alpha = Math.max(0, this.lifespan / 100);
    }

    draw(ctx) {
      ctx.beginPath();
      ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
      ctx.fillStyle = `rgba(${this.color}, ${this.alpha})`;
      ctx.fill();
    }
  }

  class Rocket {
    constructor(x, y) {
      this.x = x;
      this.y = y;
      this.color = `hsl(${Math.random() * 360}, 100%, 60%)`;
      this.particles = [];
      this.angle = Math.random() * Math.PI * 2;
      this.speed = 5 + Math.random() * 5;
      this.lifespan = 100;
      this.exploded = false;
    }

    update() {
      if (!this.exploded) {
        this.x += Math.cos(this.angle) * this.speed;
        this.y += Math.sin(this.angle) * this.speed;
        this.lifespan -= 1;
        if (this.lifespan <= 0) {
          this.explode();
        }
      } else {
        for (let p of this.particles) {
          p.update();
        }
        this.particles = this.particles.filter(p => p.lifespan > 0);
      }
    }

    explode() {
      this.exploded = true;
      const numParticles = 50;
      for (let i = 0; i < numParticles; i++) {
        const angle = Math.random() * Math.PI * 2;
        const speed = 3 + Math.random() * 4;
        const lifespan = 100 + Math.random() * 100;
        this.particles.push(new Particle(this.x, this.y, this.color, angle, speed, lifespan));
      }
    }

    draw(ctx) {
      if (!this.exploded) {
        ctx.beginPath();
        ctx.arc(this.x, this.y, 4, 0, Math.PI * 2);
        ctx.fillStyle = this.color;
        ctx.fill();
      } else {
        for (let p of this.particles) {
          p.draw(ctx);
        }
      }
    }
  }

  const rockets = [];
  let autoShow = false;
  let autoShowInterval = null;
  let autoShowCount = 0;

  function launchRocket(x, y) {
    rockets.push(new Rocket(x, y));
  }

  function animate() {
    ctx.fillStyle = "rgba(0, 0, 0, 0.2)";
    ctx.fillRect(0, 0, width, height);
    for (let rocket of rockets) {
      rocket.update();
      rocket.draw(ctx);
    }
    requestAnimationFrame(animate);
  }

  canvas.addEventListener("click", e => {
    launchRocket(e.clientX, e.clientY);
  });

  function autoShowFireworks() {
    autoShowCount++;
    launchRocket(Math.random() * width, 0);
    if (autoShowCount < 100) {
      autoShowInterval = setTimeout(autoShowFireworks, 100);
    } else {
      clearTimeout(autoShowInterval);
      autoShow = false;
    }
  }

  document.addEventListener("keydown", e => {
    if (e.code === "KeyA") {
      if (!autoShow) {
        autoShow = true;
        autoShowCount = 0;
        autoShowFireworks();
      }
    }
  });

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