124 lines
3.0 KiB
TypeScript
124 lines
3.0 KiB
TypeScript
import { reference } from "./reference.ts"
|
|
|
|
const canvas = document.querySelector("#mainCanvas");
|
|
const ctx = canvas.getContext("2d");
|
|
|
|
const dpr = window.devicePixelRatio;
|
|
const cw = window.innerWidth;
|
|
const ch = window.innerHeight;
|
|
canvas.width = cw * dpr;
|
|
canvas.height = ch * dpr;
|
|
ctx.scale(dpr, dpr);
|
|
|
|
function resize() {
|
|
canvas.width = window.innerWidth * dpr;
|
|
canvas.height = window.innerHeight * dpr;
|
|
}
|
|
|
|
window.addEventListener('resize', resize, false);
|
|
|
|
|
|
class Star {
|
|
// Star x and y are offsets from center of screen
|
|
constructor(x: number, y: number, multiplier: number) {
|
|
this.x = x;
|
|
this.y = y;
|
|
this.multiplier = multiplier;
|
|
}
|
|
|
|
canvasPos() {
|
|
return {
|
|
x: (canvas.width / 2) + this.x,
|
|
y: (canvas.height / 2) + this.y,
|
|
};
|
|
}
|
|
|
|
size() {
|
|
// Size is proportional to distance from the middle
|
|
//const dist = Math.max(this.x, this.y);
|
|
//return Math.max(1.5, dist/100);
|
|
return 1.0;
|
|
}
|
|
|
|
render(ctx) {
|
|
const { x, y } = this.canvasPos();
|
|
const r = this.size();
|
|
ctx.fillStyle = "red";
|
|
ctx.beginPath();
|
|
ctx.arc(x, y, r, 0, 2*Math.PI)
|
|
ctx.fill();
|
|
}
|
|
|
|
static make() {
|
|
const angle = Math.random() * 2*Math.PI
|
|
const x = Math.cos(angle);
|
|
const y = Math.sin(angle);
|
|
// The multiplier affects how quickly the star moves.
|
|
// Varying this makes some stars appear closer (faster
|
|
// movement), some further (slower movement).
|
|
const multiplier = 1.01 + Math.random() * 0.04;
|
|
return new Star(x, y, multiplier);
|
|
}
|
|
};
|
|
|
|
const state = {
|
|
start: null,
|
|
stars: [],
|
|
timeSinceLastStar: Infinity,
|
|
};
|
|
|
|
let start = null;
|
|
let stars = [];
|
|
let timeSinceLastStar = Infinity;
|
|
|
|
const starIntervalms = 2000;
|
|
const fadeout = 8 / 100;
|
|
|
|
function clear(ctx, alpha) {
|
|
ctx.globalCompositeOperation = "destination-out";
|
|
ctx.fillStyle = `rgba(0,0,0, ${alpha})`;
|
|
ctx.fillRect( 0, 0, canvas.width, canvas.height );
|
|
ctx.globalCompositeOperation = "lighter";
|
|
}
|
|
|
|
function loop(timestamp) {
|
|
if (state.start === null) {
|
|
state.start = timestamp;
|
|
}
|
|
const progress = timestamp - state.start
|
|
|
|
// Create a new star if it's been long enough since
|
|
// the previous one
|
|
state.timeSinceLastStar += progress;
|
|
if (state.timeSinceLastStar > starIntervalms) {
|
|
state.timeSinceLastStar = 0
|
|
state.stars.push(Star.make());
|
|
}
|
|
|
|
// Clear the screen.
|
|
// If you want the hyperspace effect, skip this.
|
|
clear(ctx, fadeout);
|
|
|
|
state.stars.forEach((star) => {
|
|
// Increase the star's distance from the middle
|
|
// proportionally to its current distance
|
|
const multiplier = star.multiplier;
|
|
star.x *= multiplier
|
|
star.y *= multiplier
|
|
star.render(ctx);
|
|
})
|
|
|
|
// Remove stars outside the view boundary
|
|
let i = state.stars.length;
|
|
while (--i) {
|
|
const star = state.stars[i];
|
|
let {x, y} = star.canvasPos();
|
|
if (x < 0 || x > canvas.width || y < 0 || y > canvas.height) {
|
|
state.stars.splice(i, 1)
|
|
}
|
|
}
|
|
window.requestAnimationFrame(loop)
|
|
}
|
|
window.requestAnimationFrame(loop)
|
|
//reference(canvas, ctx);
|