Files
OpenCut/apps/web/src/services/renderer/nodes/graphic-node.ts
T

75 lines
1.7 KiB
TypeScript

import { createOffscreenCanvas } from "../canvas-utils";
import {
DEFAULT_GRAPHIC_SOURCE_SIZE,
getGraphicDefinition,
registerDefaultGraphics,
} from "@/graphics";
import type { ParamValues } from "@/params";
import {
VisualNode,
type ResolvedVisualNodeState,
type VisualNodeParams,
} from "./visual-node";
export interface GraphicNodeParams extends VisualNodeParams {
definitionId: string;
params: ParamValues;
}
export interface ResolvedGraphicNodeState extends ResolvedVisualNodeState {
resolvedParams: ParamValues;
}
export class GraphicNode extends VisualNode<
GraphicNodeParams,
ResolvedGraphicNodeState
> {
private cachedKey: string | null = null;
private cachedSource: OffscreenCanvas | HTMLCanvasElement | null = null;
constructor(params: GraphicNodeParams) {
super(params);
registerDefaultGraphics();
}
getSource({
resolvedParams,
}: {
resolvedParams: ParamValues;
}): OffscreenCanvas | HTMLCanvasElement | null {
const definition = getGraphicDefinition({
definitionId: this.params.definitionId,
});
const cacheKey = JSON.stringify({
definitionId: this.params.definitionId,
params: resolvedParams,
});
if (this.cachedSource && this.cachedKey === cacheKey) {
return this.cachedSource;
}
const canvas = createOffscreenCanvas({
width: DEFAULT_GRAPHIC_SOURCE_SIZE,
height: DEFAULT_GRAPHIC_SOURCE_SIZE,
});
const ctx = canvas.getContext("2d") as
| CanvasRenderingContext2D
| OffscreenCanvasRenderingContext2D
| null;
if (!ctx) {
return null;
}
definition.render({
ctx,
params: resolvedParams,
width: DEFAULT_GRAPHIC_SOURCE_SIZE,
height: DEFAULT_GRAPHIC_SOURCE_SIZE,
});
this.cachedKey = cacheKey;
this.cachedSource = canvas;
return canvas;
}
}