3 Commits
v1.2.1 ... main

Author SHA1 Message Date
3c1aa4fbe4 Use OffscreenCanvas instead of HTMLCanvasElement for buffers 2025-04-02 20:35:09 -07:00
9b58e864a2 Proper image loading 2025-04-02 20:30:57 -07:00
4b99a1c26e Fix oversights in bg renderer
So it turns out the performance improvements were completelty neglected
because my code is bad. The buffer wasn't getting rendered to the canvas
in the best way, and there were too many particles for smaller screens.
I have now added a simple math equasion to the init function that
decides how many particles are needed based on the display size. It
still needs a lot of tweaking, and a more complex function is probably
necessary for good results. I'm still trying to get this background to
not suck and actually look good.
2025-04-02 19:49:37 -07:00

View File

@ -8,36 +8,46 @@
let dark_theme = false;
let time_scale = 1;
let particlesArray: Array<Particle> = [];
let gradientsArray: Array<Gradient> = [];
let particleImages: { [key: string]: HTMLImageElement } = {};
let particleImages = {
// This is horrible code
circle: {} as HTMLImageElement,
square: {} as HTMLImageElement,
triangle: {} as HTMLImageElement,
star: {} as HTMLImageElement,
wavyCircle: {} as HTMLImageElement,
};
async function loadImg(src: string): Promise<HTMLImageElement> {
return new Promise((resolve, reject) => {
let img = new Image();
img.onload = () => resolve(img);
img.onerror = reject;
img.src = src;
});
}
onMount(() => {
let particles: Particle[] = [];
let gradients: Gradient[] = [];
onMount(async () => {
canvas = document.getElementById("bg-canvas") as HTMLCanvasElement;
ctx = canvas.getContext("2d") as CanvasRenderingContext2D;
particleImages.circle = new Image() as HTMLImageElement;
particleImages.circle.src = "/img/bg-shapes/circle.svg";
let imagePromises = {
circle: loadImg("/img/bg-shapes/circle.svg"),
square: loadImg("/img/bg-shapes/square.svg"),
triangle: loadImg("/img/bg-shapes/triangle.svg"),
star: loadImg("/img/bg-shapes/star.svg"),
wavyCircle: loadImg("/img/bg-shapes/wavy-circle.svg"),
};
particleImages.square = new Image() as HTMLImageElement;
particleImages.square.src = "/img/bg-shapes/square.svg";
particleImages.triangle = new Image() as HTMLImageElement;
particleImages.triangle.src = "/img/bg-shapes/triangle.svg";
particleImages.star = new Image() as HTMLImageElement;
particleImages.star.src = "/img/bg-shapes/star.svg";
particleImages.wavyCircle = new Image() as HTMLImageElement;
particleImages.wavyCircle.src = "/img/bg-shapes/wavy-circle.svg";
particleImages = await Promise.all(Object.values(imagePromises))
.then((imgs) => {
return {
circle: imgs[0],
square: imgs[1],
triangle: imgs[2],
star: imgs[3],
wavyCircle: imgs[4],
};
})
.catch((error) => {
console.error("Error loading images:", error);
return {};
});
if (
window.matchMedia &&
@ -50,8 +60,8 @@
.matchMedia("(prefers-color-scheme: dark)")
.addEventListener("change", (event) => {
dark_theme = event.matches;
for (let i = 0; i < gradientsArray.length; i++) {
let gradient = gradientsArray[i];
for (let i = 0; i < gradients.length; i++) {
let gradient = gradients[i];
gradient.color = getRandomColor();
gradient.prepareBuffer();
}
@ -221,30 +231,31 @@
radius: number;
color: string;
alpha: number;
renderingBuffer: HTMLCanvasElement;
renderingBuffer: OffscreenCanvas;
constructor() {
super();
this.radius = Math.random() * 500 + 300;
this.color = getRandomColor();
this.alpha = Math.random() * 0.5 + 0.5; // Initial alpha between 0.5 and 1
this.renderingBuffer = document.createElement(
"canvas",
) as HTMLCanvasElement;
this.renderingBuffer = new OffscreenCanvas(
this.radius * 2,
this.radius * 2,
);
// One-shot buffer adjustment
this.renderingBuffer.width = this.radius * 2;
this.renderingBuffer.height = this.radius * 2;
canvasDpiScaler(
this.renderingBuffer,
this.renderingBuffer.getContext("2d") as CanvasRenderingContext2D,
);
// canvasDpiScaler(
// this.renderingBuffer,
// this.renderingBuffer.getContext("2d") as CanvasRenderingContext2D,
// );
this.prepareBuffer();
}
prepareBuffer() {
let bctx = this.renderingBuffer.getContext(
"2d",
) as CanvasRenderingContext2D;
) as OffscreenCanvasRenderingContext2D;
bctx.clearRect(
0,
@ -276,36 +287,44 @@
}
draw() {
ctx.drawImage(
this.renderingBuffer,
this.x - this.radius,
this.y - this.radius,
);
ctx.save();
ctx.translate(this.x - this.radius, this.y - this.radius);
ctx.drawImage(this.renderingBuffer, 0, 0);
ctx.restore();
}
}
function init() {
particlesArray = [];
for (let i = 0; i < 50; i++) {
particlesArray.push(new Particle());
/*/
* Calculate the proper amount of particles
* 25920 is our constant, equal to x in (1080*1920)/x = 80
* Because the subjectively correct amount of particles for a 1080p
* display is 80, so to calculate the proper amount for any window size,
* just do (width * height) / 25920
/*/
let particleCount = (window.innerWidth * window.innerHeight) / 25920;
particles = [];
for (let i = 0; i < particleCount; i++) {
particles.push(new Particle());
}
gradientsArray = [];
gradients = [];
for (let i = 0; i < 10; i++) {
gradientsArray.push(new Gradient());
gradients.push(new Gradient());
}
}
function animate() {
ctx.clearRect(0, 0, window.innerWidth, window.innerHeight);
for (let i_gradient = 0; i_gradient < gradientsArray.length; i_gradient++) {
let gradient = gradientsArray[i_gradient];
for (let i_gradient = 0; i_gradient < gradients.length; i_gradient++) {
let gradient = gradients[i_gradient];
gradient.update();
gradient.draw();
}
for (let i_particle = 0; i_particle < particlesArray.length; i_particle++) {
let particle = particlesArray[i_particle];
for (let i_particle = 0; i_particle < particles.length; i_particle++) {
let particle = particles[i_particle];
particle.update();
particle.draw();
}