← back to Model Arena

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

130 lines

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Fractal Tree</title>
  <style>
    html, body {
      margin: 0;
      padding: 0;
      overflow: hidden;
      background: #222;
      height: 100%;
      width: 100%;
    }
    canvas {
      display: block;
    }
    #slider {
      position: absolute;
      top: 10px;
      left: 10px;
      width: 200px;
    }
  </style>
</head>
<body>
<canvas id="canvas"></canvas>
<input type="range" id="slider" min="1" max="10" value="5">
<script>
  const canvas = document.getElementById('canvas');
  const ctx = canvas.getContext('2d');
  const slider = document.getElementById('slider');

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

  let depth = 5;
  let wind = 0;
  let frame = 0;

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

  const leaves = [];
  const leafCount = 100;

  function createLeaf() {
    const leaf = {
      x: Math.random() * canvas.width,
      y: Math.random() * canvas.height,
      size: Math.random() * 4 + 2,
      alpha: 1,
      fallSpeed: Math.random() * 0.5 + 0.2,
      rotation: Math.random() * Math.PI * 2,
      angleSpeed: (Math.random() - 0.5) * 0.05
    };
    leaves.push(leaf);
  }

  for (let i = 0; i < leafCount; i++) {
    createLeaf();
  }

  function drawLeaf(leaf) {
    ctx.save();
    ctx.translate(leaf.x, leaf.y);
    ctx.rotate(leaf.rotation);
    ctx.fillStyle = `rgba(34, 139, 34, ${leaf.alpha})`;
    ctx.beginPath();
    ctx.arc(0, 0, leaf.size, 0, Math.PI * 2);
    ctx.fill();
    ctx.restore();
    leaf.y += leaf.fallSpeed;
    leaf.rotation += leaf.angleSpeed;
    leaf.alpha -= 0.005;
    if (leaf.alpha <= 0) {
      createLeaf();
    }
  }

  function drawTree(x, y, length, angle, branchWidth, branchDepth) {
    if (branchDepth === 0) return;

    const newX = x + Math.cos(angle) * length;
    const newY = y + Math.sin(angle) * length;
    const newAngle = angle + (Math.random() - 0.5) * 0.3 + wind * 0.1;
    const newLength = length * 0.7;
    const newBranchWidth = branchWidth * 0.7;
    const newBranchDepth = branchDepth - 1;

    ctx.beginPath();
    ctx.moveTo(x, y);
    ctx.lineTo(newX, newY);
    ctx.strokeStyle = `hsl(${(frame % 255) + 120}, 80%, 50%)`;
    ctx.lineWidth = branchWidth;
    ctx.stroke();

    if (branchDepth > 2 && Math.random() < 0.3) {
      ctx.fillStyle = `hsl(${(frame % 255) + 120}, 80%, 50%)`;
      ctx.beginPath();
      ctx.arc(newX, newY, 8, 0, Math.PI * 2);
      ctx.fill();
    }

    drawTree(newX, newY, newLength, newAngle, newBranchWidth, newBranchDepth);
    drawTree(newX, newY, newLength, newAngle - 0.3, newBranchWidth, newBranchDepth);
    drawTree(newX, newY, newLength, newAngle + 0.3, newBranchWidth, newBranchDepth);
  }

  function animate() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    wind = Math.sin(frame * 0.01) * 0.1;
    drawTree(canvas.width / 2, canvas.height - 50, 100, -Math.PI / 2, 10, depth);
    leaves.forEach(drawLeaf);
    frame++;
    requestAnimationFrame(animate);
  }

  slider.addEventListener('input', () => {
    depth = parseInt(slider.value);
  });

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