Learn to create a classic 3D starfield effect using HTML5 Canvas
A starfield effect simulates flying through space by:
<canvas id="starfield" width="800" height="600"></canvas>
<script>
const canvas = document.getElementById('starfield');
const ctx = canvas.getContext('2d');
const width = canvas.width;
const height = canvas.height;
const centerX = width / 2;
const centerY = height / 2;
</script>
class Star {
constructor() {
this.reset();
}
reset() {
// Random position in 3D space
this.x = Math.random() * 1600 - 800; // -800 to 800
this.y = Math.random() * 1200 - 600; // -600 to 600
this.z = Math.random() * 1000; // 0 to 1000
}
update(speed) {
// Move star toward camera (decrease z)
this.z -= speed;
// Reset if star passes camera
if (this.z < 1) {
this.reset();
this.z = 1000;
}
}
draw(ctx, centerX, centerY) {
// Perspective projection
const k = 128 / this.z;
const px = this.x * k + centerX;
const py = this.y * k + centerY;
// Star size based on depth
const size = (1 - this.z / 1000) * 2;
// Brightness based on depth
const brightness = (1 - this.z / 1000) * 255;
ctx.fillStyle = `rgb(${brightness}, ${brightness}, ${brightness})`;
ctx.fillRect(px, py, size, size);
}
}
const numStars = 500;
const stars = [];
for (let i = 0; i < numStars; i++) {
stars.push(new Star());
}
let speed = 5;
let paused = false;
function animate() {
// Clear canvas with fade effect for trails
ctx.fillStyle = 'rgba(0, 0, 0, 0.2)';
ctx.fillRect(0, 0, width, height);
if (!paused) {
// Update and draw each star
stars.forEach(star => {
star.update(speed);
star.draw(ctx, centerX, centerY);
});
}
requestAnimationFrame(animate);
}
animate();
// Pause/Resume
document.getElementById('pauseBtn').addEventListener('click', () => {
paused = !paused;
});
// Speed control
document.getElementById('speedUpBtn').addEventListener('click', () => {
speed += 2;
});
document.getElementById('slowDownBtn').addEventListener('click', () => {
speed = Math.max(1, speed - 2);
});