Skip to content

Instantly share code, notes, and snippets.

@charafmrah
Created March 11, 2023 15:53
Show Gist options
  • Save charafmrah/51db55e98a8a9c5f9a687e2fd0532faf to your computer and use it in GitHub Desktop.
Save charafmrah/51db55e98a8a9c5f9a687e2fd0532faf to your computer and use it in GitHub Desktop.
Starfield
<div id="starfield" class="absolute inset-0">
<canvas id="starfield-canvas"></canvas>
</div>
<script>
import invariant from "tiny-invariant";
const COUNT = 800;
const SPEED = 0.1;
class Star {
x: number;
y: number;
z: number;
xPrev: number;
yPrev: number;
constructor(x = 0, y = 0, z = 0) {
this.x = x;
this.y = y;
this.z = z;
this.xPrev = x;
this.yPrev = y;
}
update(width: number, height: number, speed: number) {
this.xPrev = this.x;
this.yPrev = this.y;
this.z += speed * 0.0675;
this.x += this.x * (speed * 0.0225) * this.z;
this.y += this.y * (speed * 0.0225) * this.z;
if (
this.x > width / 2 ||
this.x < -width / 2 ||
this.y > height / 2 ||
this.y < -height / 2
) {
this.x = Math.random() * width - width / 2;
this.y = Math.random() * height - height / 2;
this.xPrev = this.x;
this.yPrev = this.y;
this.z = 0;
}
}
draw(ctx: CanvasRenderingContext2D) {
ctx.lineWidth = this.z;
ctx.beginPath();
ctx.moveTo(this.x, this.y);
ctx.lineTo(this.xPrev, this.yPrev);
ctx.stroke();
}
}
const stars = Array.from({ length: COUNT }, () => new Star(0, 0, 0));
let rafId = 0;
const canvas = document.querySelector(
"#starfield-canvas"
) as HTMLCanvasElement;
invariant(canvas, "canvas should not be null");
const ctx = canvas.getContext("2d");
const container = document.querySelector("#starfield") as HTMLElement;
invariant(container, "container should not be null");
const resizeObserver = new ResizeObserver(setup);
resizeObserver.observe(container);
function setup() {
invariant(ctx, "canvas context should not be null");
rafId > 0 && cancelAnimationFrame(rafId);
const { clientWidth: width, clientHeight: height } = container;
const dpr = window.devicePixelRatio || 1;
canvas.width = width * dpr;
canvas.height = height * dpr;
canvas.style.width = `${width}px`;
canvas.style.height = `${height}px`;
ctx.scale(dpr, dpr);
for (const star of stars) {
star.x = Math.random() * width - width / 2;
star.y = Math.random() * height - height / 2;
star.z = 0;
}
ctx.translate(width / 2, height / 2);
ctx.fillStyle = "rgba(0, 0, 0, 0.4)";
ctx.strokeStyle = "white";
rafId = requestAnimationFrame(frame);
}
function frame() {
invariant(ctx, "canvas context should not be null");
const { clientWidth: width, clientHeight: height } = container;
for (const star of stars) {
star.update(width, height, SPEED);
star.draw(ctx);
}
ctx.fillRect(-width / 2, -height / 2, width, height);
rafId = requestAnimationFrame(frame);
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment