canvas-compositor/Compositor/Canvas.ts

148 lines
4.6 KiB
TypeScript
Raw Permalink Normal View History

2023-06-11 16:01:50 +03:00
import Node from "./Node";
import NodeEvent from "./NodeEvent";
export default class Canvas
{
public context : CanvasRenderingContext2D;
public canvas : HTMLCanvasElement;
public width : number;
public height : number;
public rootNode = new Node("Root");
public nodes: [Node,number][] = [];
public pool : DrawPool = new DrawPool();
public constructor()
{
this.canvas = document.createElement("canvas");
this.context = this.canvas.getContext("2d") as CanvasRenderingContext2D;
this.installMouseManager();
this.installKeyboardManager();
}
public init()
{
this.canvas.style.imageRendering = "pixelated";
window.document.body.appendChild(this.canvas);
this.recalculateSize();
window.addEventListener("resize",() => this.recalculateSize());
this.pool.trigger = () => this.drawContext();
}
public installMouseManager()
{
this.canvas.addEventListener("mousedown",(event) => {
let mouseEvent = new NodeEvent();
mouseEvent.x = event.offsetX;
mouseEvent.y = event.offsetY;
mouseEvent.type = "mouse:down";
this.rootNode.emit("mouse", mouseEvent);
});
this.canvas.addEventListener("mousemove",(event) => {
let mouseEvent = new NodeEvent();
mouseEvent.x = event.offsetX;
mouseEvent.y = event.offsetY;
mouseEvent.data = {
deltaX: event.movementX,
deltaY: event.movementY
};
mouseEvent.type = "mouse:move";
this.rootNode.emit("mouse", mouseEvent);
});
this.canvas.addEventListener("mouseup",(event) => {
let mouseEvent = new NodeEvent();
mouseEvent.x = event.offsetX;
mouseEvent.y = event.offsetY;
mouseEvent.type = "mouse:up";
this.rootNode.emit("mouse", mouseEvent);
});
this.canvas.addEventListener("click",(event) => {
let mouseEvent = new NodeEvent();
mouseEvent.x = event.offsetX;
mouseEvent.y = event.offsetY;
mouseEvent.type = "mouse:click";
this.rootNode.emit("mouse", mouseEvent);
});
this.canvas.addEventListener("wheel",(event) => {
let mouseEvent = new NodeEvent();
mouseEvent.x = event.offsetX;
mouseEvent.y = event.offsetY;
mouseEvent.data = {
xModulus: event.deltaX == 0 ? 0 : event.deltaX < 0 ? -1 : +1,
yModulus: event.deltaY == 0 ? 0 : event.deltaY < 0 ? -1 : +1,
xScroll: event.deltaX,
yScroll: event.deltaY
};
mouseEvent.type = "mouse:wheel";
this.rootNode.emit("mouse", mouseEvent);
});
}
public installKeyboardManager()
{
}
public recalculateSize()
{
let {
width,
height
} = document.body.getClientRects()[0];
this.canvas.setAttribute("width", width + "px");
this.canvas.setAttribute("height", height + "px");
this.canvas.style.width = width + "px";
this.canvas.style.height = height + "px";
this.width = width;
this.height = height
this.pool.notify();
}
public addNode(node:Node, priority : number= 0)
{
this.nodes.push([node,priority]);
node.on('draw',() => {
this.pool.notify();
});
this.pool.notify();
}
public drawContext()
{
this.rootNode.width = this.width;
this.rootNode.height = this.height;
this.rootNode.ChildNodes = this.nodes.sort(([,n], [,k]) => n - k).map(e => e[0]);
this.context.clearRect(0, 0, this.width, this.height);
this.rootNode.context.resize(this.rootNode.width, this.rootNode.height);
this.rootNode.draw().writeTo(
this.context,
0,
0,
this.rootNode.width,
this.rootNode.height,
0,
0,
this.rootNode.width,
this.rootNode.height
);
}
};
class DrawPool
{
public busy : boolean = true;
public trigger : Function;
public inf : number = -1;
public addPool(e:Function)
{
if(!this.busy)
{
this.notify()
}else this.trigger = e;
}
public notify()
{
this.busy = true;
this.inf = requestAnimationFrame(() => {
if(this.trigger)
{
this.trigger();
}
this.busy = false;
});
}
}