148 lines
4.6 KiB
TypeScript
148 lines
4.6 KiB
TypeScript
|
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;
|
||
|
});
|
||
|
}
|
||
|
}
|