mirror of
https://git.sfja.dk/sfja/h6-logicirc.git
synced 2025-05-16 01:08:07 +01:00
129 lines
3.2 KiB
TypeScript
129 lines
3.2 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);
|
|
}
|
|
|
|
strokeRect(
|
|
x: number,
|
|
y: number,
|
|
w: number,
|
|
h: number,
|
|
color: string,
|
|
lineWidth: number,
|
|
): void {
|
|
const { g } = this;
|
|
g.strokeStyle = color;
|
|
g.lineWidth = lineWidth;
|
|
g.strokeRect(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,
|
|
alpha = 1,
|
|
): void {
|
|
const { g } = this;
|
|
g.globalAlpha = alpha;
|
|
g.drawImage(data, x, y, w, h);
|
|
g.globalAlpha = 1.0;
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|