summaryrefslogtreecommitdiff
path: root/apps/web/src/services/renderer/canvas-renderer.ts
diff options
context:
space:
mode:
authorMaze <167211895+mazeincoding@users.noreply.github.com>2026-01-31 00:20:04 +0100
committerGitHub <noreply@github.com>2026-01-31 00:20:04 +0100
commit7bf0984698e43b9aa2dd879f65951318ed410390 (patch)
treeccf2cd590a47d550152afc07129cb55c71a9ec35 /apps/web/src/services/renderer/canvas-renderer.ts
parent0173db99448d1c4c6415dcf15272e17551b48b04 (diff)
downloadopencut-7bf0984698e43b9aa2dd879f65951318ed410390.tar.gz
codebase overhaul (#697)
Diffstat (limited to 'apps/web/src/services/renderer/canvas-renderer.ts')
-rw-r--r--apps/web/src/services/renderer/canvas-renderer.ts87
1 files changed, 87 insertions, 0 deletions
diff --git a/apps/web/src/services/renderer/canvas-renderer.ts b/apps/web/src/services/renderer/canvas-renderer.ts
new file mode 100644
index 00000000..840d8b52
--- /dev/null
+++ b/apps/web/src/services/renderer/canvas-renderer.ts
@@ -0,0 +1,87 @@
+import type { BaseNode } from "./nodes/base-node";
+
+export type CanvasRendererParams = {
+ width: number;
+ height: number;
+ fps: number;
+};
+
+export class CanvasRenderer {
+ canvas: OffscreenCanvas | HTMLCanvasElement;
+ context: OffscreenCanvasRenderingContext2D | CanvasRenderingContext2D;
+ width: number;
+ height: number;
+ fps: number;
+
+ constructor({ width, height, fps }: CanvasRendererParams) {
+ this.width = width;
+ this.height = height;
+ this.fps = fps;
+
+ try {
+ this.canvas = new OffscreenCanvas(width, height);
+ } catch {
+ this.canvas = document.createElement("canvas");
+ this.canvas.width = width;
+ this.canvas.height = height;
+ }
+
+ const context = this.canvas.getContext("2d");
+ if (!context) {
+ throw new Error("Failed to get canvas context");
+ }
+
+ this.context = context as
+ | OffscreenCanvasRenderingContext2D
+ | CanvasRenderingContext2D;
+ }
+
+ setSize({ width, height }: { width: number; height: number }) {
+ this.width = width;
+ this.height = height;
+
+ if (this.canvas instanceof OffscreenCanvas) {
+ this.canvas = new OffscreenCanvas(width, height);
+ } else {
+ this.canvas.width = width;
+ this.canvas.height = height;
+ }
+
+ const context = this.canvas.getContext("2d");
+ if (!context) {
+ throw new Error("Failed to get canvas context");
+ }
+ this.context = context as
+ | OffscreenCanvasRenderingContext2D
+ | CanvasRenderingContext2D;
+ }
+
+ private clear() {
+ this.context.fillStyle = "black";
+ this.context.fillRect(0, 0, this.canvas.width, this.canvas.height);
+ }
+
+ async render({ node, time }: { node: BaseNode; time: number }) {
+ this.clear();
+ await node.render({ renderer: this, time });
+ }
+
+ async renderToCanvas({
+ node,
+ time,
+ targetCanvas,
+ }: {
+ node: BaseNode;
+ time: number;
+ targetCanvas: HTMLCanvasElement;
+ }) {
+ await this.render({ node, time });
+
+ const ctx = targetCanvas.getContext("2d");
+ if (!ctx) {
+ throw new Error("Failed to get target canvas context");
+ }
+
+ ctx.drawImage(this.canvas, 0, 0, targetCanvas.width, targetCanvas.height);
+ }
+}