h6-logicirc/src/canvas.ts
2025-05-07 16:26:39 +02:00

112 lines
2.9 KiB
TypeScript

import { EvHandler, EvHandlerRes, Mouse } from "./input.ts";
import { Renderer, RendererImage } from "./renderer.ts";
export class CanvasRenderer implements Renderer {
constructor(
private c: HTMLCanvasElement,
private g: CanvasRenderingContext2D,
) {}
get width(): number {
return this.c.width;
}
get height(): number {
return this.c.height;
}
clear(color: string): void {
const { g } = this;
g.fillStyle = color;
g.fillRect(0, 0, this.c.width, this.c.height);
}
fillRect(x: number, y: number, w: number, h: number, color: string): void {
const { g } = this;
g.fillStyle = color;
g.fillRect(x, y, w, h);
}
fillCirc(x: number, y: number, radius: number, color: string): void {
const { g } = this;
g.fillStyle = color;
g.beginPath();
g.arc(x, y, radius, 0, Math.PI * 2);
g.fill();
}
putImage(
data: RendererImage,
x: number,
y: number,
w = data.width,
h = data.height,
): void {
const { g } = this;
g.drawImage(data, x, y, w, h);
}
}
export class CanvasMouse implements Mouse {
public x = 0;
public y = 0;
private pressHandlers: EvHandler[] = [];
private releaseHandlers: EvHandler[] = [];
private moveHandlers: EvHandler[] = [];
private scrollHandlers: ((direction: "up" | "down") => EvHandlerRes)[] = [];
constructor(c: HTMLCanvasElement) {
c.onmousemove = (ev) => {
this.x = ev.x;
this.y = ev.y;
};
c.onmousedown = (ev) => {
if (ev.button === 0) {
this.runHandlers(this.pressHandlers);
}
};
c.onmouseup = (ev) => {
if (ev.button === 0) {
this.runHandlers(this.releaseHandlers);
}
};
c.onmousemove = (ev) => {
this.x = ev.x;
this.y = ev.y;
this.runHandlers(this.moveHandlers);
};
c.onwheel = (ev) => {
if (ev.deltaY !== 0) {
this.runHandlers(
this.scrollHandlers,
ev.deltaY < 0 ? "up" : "down",
);
}
};
}
private runHandlers<Args extends unknown[] = []>(
handlers: EvHandler<Args>[],
...args: Args
) {
for (const handler of handlers.toReversed()) {
if (handler(...args) === "stop") {
break;
}
}
}
addOnPress(handler: EvHandler) {
this.pressHandlers.push(handler);
}
addOnRelease(handler: EvHandler) {
this.releaseHandlers.push(handler);
}
addOnMove(handler: EvHandler) {
this.moveHandlers.push(handler);
}
addOnScroll(handler: EvHandler<["up" | "down"]>) {
this.scrollHandlers.push(handler);
}
}