ソースコード抜粋
<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>
コメント