JavaScriptでワイヤーフレームによる3D球体回転アニメーション

コンピュータ

ソースコード抜粋

<canvas id="canvas" width="600" height="600"></canvas>

<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const width = canvas.width;
const height = canvas.height;
const center = { x: width / 2, y: height / 2 };

const radius = 200;
const longitudeLines = 24; // 経度線
const latitudeLines = 12;  // 緯度線

let angle = 0;

function project(x, y, z) {
  const scale = 300 / (z + 400); // 遠くの点は小さく見える
  return {
    x: center.x + x * scale,
    y: center.y + y * scale
  };
}

function rotateY(x, z, theta) {
  const sin = Math.sin(theta);
  const cos = Math.cos(theta);
  return {
    x: x * cos - z * sin,
    z: x * sin + z * cos
  };
}

function drawSphere() {
  ctx.clearRect(0, 0, width, height);

  // 緯度線 (横方向)
  for (let i = 1; i < latitudeLines; i++) {
    const lat = Math.PI * i / latitudeLines - Math.PI / 2;
    const y = radius * Math.sin(lat);
    const r = radius * Math.cos(lat);

    ctx.beginPath();
    for (let j = 0; j <= 360; j += 5) {
      const lon = j * Math.PI / 180;
      let x = r * Math.cos(lon);
      let z = r * Math.sin(lon);

      // 回転
      const rotated = rotateY(x, z, angle);
      x = rotated.x;
      z = rotated.z;

      const p = project(x, y, z);
      if (j === 0) ctx.moveTo(p.x, p.y);
      else ctx.lineTo(p.x, p.y);
    }
    ctx.strokeStyle = '#0f0';
    ctx.stroke();
  }

  // 経度線 (縦方向)
  for (let i = 0; i < longitudeLines; i++) {
    const lon = 2 * Math.PI * i / longitudeLines;

    ctx.beginPath();
    for (let j = -90; j <= 90; j += 5) {
      const lat = j * Math.PI / 180;
      let x = radius * Math.cos(lat) * Math.cos(lon);
      let y = radius * Math.sin(lat);
      let z = radius * Math.cos(lat) * Math.sin(lon);

      // 回転
      const rotated = rotateY(x, z, angle);
      x = rotated.x;
      z = rotated.z;

      const p = project(x, y, z);
      if (j === -90) ctx.moveTo(p.x, p.y);
      else ctx.lineTo(p.x, p.y);
    }
    ctx.strokeStyle = '#0af';
    ctx.stroke();
  }
}

function animate() {
  angle += 0.01;
  drawSphere();
  requestAnimationFrame(animate);
}

animate();
</script>

コメント