Yedek
This commit is contained in:
commit
a187e04b80
|
@ -0,0 +1,148 @@
|
|||
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;
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,168 @@
|
|||
export default class CanvasBuffer
|
||||
{
|
||||
public offscreen! : OffscreenCanvas;
|
||||
public context! : OffscreenCanvasRenderingContext2D;
|
||||
public width: number = 0;
|
||||
public height: number = 0;
|
||||
constructor(width?:number, height?:number){
|
||||
this.offscreen = new OffscreenCanvas(width || 0, height || 0);
|
||||
this.context = this.offscreen.getContext("2d") as OffscreenCanvasRenderingContext2D;
|
||||
this.width = width || 0;
|
||||
this.height = height || 0;
|
||||
}
|
||||
public resize(width: number, height: number)
|
||||
{
|
||||
if(this.width != width)
|
||||
{
|
||||
this.offscreen.width = width;
|
||||
this.width = width || 0;
|
||||
}
|
||||
if(this.height != height)
|
||||
{
|
||||
this.offscreen.height = height;
|
||||
this.height = height || 0;
|
||||
}
|
||||
}
|
||||
public clear()
|
||||
{
|
||||
this.context.clearRect(0, 0, this.offscreen.width, this.offscreen.height);
|
||||
}
|
||||
public writeFrom(
|
||||
canvas: OffscreenCanvas | OffscreenCanvasRenderingContext2D | HTMLCanvasElement | CanvasRenderingContext2D | CanvasBuffer,
|
||||
x?:number,
|
||||
y?:number,
|
||||
width?:number,
|
||||
height?:number,
|
||||
dx?:number,
|
||||
dy?:number,
|
||||
dwidth?:number,
|
||||
dheight?:number
|
||||
)
|
||||
{
|
||||
let args = [
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
dx,
|
||||
dy,
|
||||
dwidth,
|
||||
dheight
|
||||
];
|
||||
if(
|
||||
canvas instanceof OffscreenCanvas ||
|
||||
canvas instanceof HTMLCanvasElement
|
||||
)
|
||||
{
|
||||
_draw_content_to_canvas(
|
||||
this.context,
|
||||
canvas,
|
||||
...args
|
||||
);
|
||||
}
|
||||
if(
|
||||
canvas instanceof OffscreenCanvasRenderingContext2D ||
|
||||
canvas instanceof CanvasRenderingContext2D
|
||||
)
|
||||
{
|
||||
_draw_content_to_canvas(
|
||||
this.context,
|
||||
canvas.canvas,
|
||||
...args
|
||||
);
|
||||
}
|
||||
if(
|
||||
canvas instanceof CanvasBuffer
|
||||
)
|
||||
{
|
||||
_draw_content_to_canvas(
|
||||
this.context,
|
||||
canvas.offscreen,
|
||||
...args
|
||||
);
|
||||
}
|
||||
}
|
||||
public writeTo(
|
||||
canvas: OffscreenCanvas | OffscreenCanvasRenderingContext2D | HTMLCanvasElement | CanvasRenderingContext2D | CanvasBuffer,
|
||||
x?:number,
|
||||
y?:number,
|
||||
width?:number,
|
||||
height?:number,
|
||||
dx?:number,
|
||||
dy?:number,
|
||||
dwidth?:number,
|
||||
dheight?:number
|
||||
)
|
||||
{
|
||||
let args = [
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
dx,
|
||||
dy,
|
||||
dwidth,
|
||||
dheight
|
||||
];
|
||||
if(
|
||||
canvas instanceof OffscreenCanvas ||
|
||||
canvas instanceof HTMLCanvasElement
|
||||
)
|
||||
{
|
||||
let content = canvas.getContext("2d") as OffscreenCanvasRenderingContext2D | CanvasRenderingContext2D;
|
||||
|
||||
_draw_content_to_canvas(
|
||||
content,
|
||||
this.offscreen,
|
||||
...args
|
||||
);
|
||||
}
|
||||
if(
|
||||
canvas instanceof OffscreenCanvasRenderingContext2D ||
|
||||
canvas instanceof CanvasRenderingContext2D
|
||||
)
|
||||
{
|
||||
_draw_content_to_canvas(
|
||||
canvas,
|
||||
this.offscreen,
|
||||
...args
|
||||
);
|
||||
}
|
||||
if(
|
||||
canvas instanceof CanvasBuffer
|
||||
)
|
||||
{
|
||||
_draw_content_to_canvas(
|
||||
canvas.context,
|
||||
this.offscreen,
|
||||
...args
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _draw_content_to_canvas(
|
||||
context : OffscreenCanvasRenderingContext2D | CanvasRenderingContext2D,
|
||||
canvas : OffscreenCanvas | HTMLCanvasElement,
|
||||
x?:number,
|
||||
y?:number,
|
||||
width?:number,
|
||||
height?:number,
|
||||
dx?:number,
|
||||
dy?:number,
|
||||
dwidth?:number,
|
||||
dheight?:number
|
||||
)
|
||||
{
|
||||
context.drawImage(
|
||||
canvas,
|
||||
x || 0,
|
||||
y || 0,
|
||||
width || canvas.width,
|
||||
height || canvas.height,
|
||||
dx || 0,
|
||||
dy || 0,
|
||||
dwidth || canvas.width,
|
||||
dheight || canvas.height
|
||||
)
|
||||
}
|
|
@ -0,0 +1,409 @@
|
|||
|
||||
type DrawArea = {width:number,height:number};
|
||||
type DrawFunction<T> = (this: T, ctx: CanvasBuffer,area:DrawArea) => any;
|
||||
import CanvasBuffer from "./CanvasBuffer";
|
||||
import NodeEvent from "./NodeEvent";
|
||||
|
||||
export default class Node
|
||||
{
|
||||
public name = "";
|
||||
|
||||
public context : CanvasBuffer = new CanvasBuffer();
|
||||
|
||||
protected buffered : boolean = false;
|
||||
protected requiredRedraw : boolean = true;
|
||||
|
||||
public ChildNodes : Node[] = [];
|
||||
public parentNode? : Node;
|
||||
|
||||
public width : number = 0;
|
||||
public height : number = 0;
|
||||
public x : number = 0;
|
||||
public y : number = 0;
|
||||
public scale : number = 1;
|
||||
public rotate = 0;
|
||||
|
||||
public mouseHover : boolean = false;
|
||||
|
||||
public padding = {
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: 0,
|
||||
bottom: 0
|
||||
};
|
||||
constructor(name?:string)
|
||||
{
|
||||
this.name = name || "";
|
||||
}
|
||||
public update()
|
||||
{
|
||||
this.requiredRedraw = true;
|
||||
if(this.parentNode)
|
||||
{
|
||||
this.parentNode.update();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.emit("draw", new NodeEvent(), false);
|
||||
}
|
||||
}
|
||||
public draw(maxWidth?: number, maxHeight?: number) : CanvasBuffer
|
||||
{
|
||||
let drawableAreaWidth = this.width;
|
||||
let drawableAreaHeight = this.height;
|
||||
|
||||
if(maxWidth)
|
||||
{
|
||||
drawableAreaWidth = Math.min(drawableAreaWidth, maxWidth);
|
||||
}
|
||||
if(maxHeight)
|
||||
{
|
||||
drawableAreaHeight = Math.min(drawableAreaHeight, maxHeight);
|
||||
}
|
||||
|
||||
if(this.hasEvent("draw"))
|
||||
{
|
||||
let cancelDraw = false;
|
||||
this.handleEvent("draw:before",(callback) => {
|
||||
|
||||
return callback.call(this,{
|
||||
drawableAreaWidth,
|
||||
drawableAreaHeight
|
||||
})
|
||||
|
||||
});
|
||||
|
||||
let frame = this.handleEvent("draw",(event) => {
|
||||
let offscreen = new CanvasBuffer(drawableAreaWidth, drawableAreaHeight);
|
||||
|
||||
cancelDraw = event.apply(this, [
|
||||
offscreen, {
|
||||
width: drawableAreaWidth,
|
||||
height: drawableAreaHeight
|
||||
}
|
||||
]);
|
||||
return offscreen;
|
||||
}) as CanvasBuffer;
|
||||
|
||||
this.context = frame;
|
||||
this.buffered = true;
|
||||
|
||||
this.handleEvent("draw:after",(callback) => {
|
||||
|
||||
return callback.call(this,{
|
||||
drawableAreaWidth,
|
||||
drawableAreaHeight
|
||||
})
|
||||
|
||||
});
|
||||
if(!cancelDraw)
|
||||
{
|
||||
return frame;
|
||||
}
|
||||
};
|
||||
|
||||
let width = drawableAreaWidth - (this.padding.right + this.padding.left);
|
||||
let height = drawableAreaHeight - (this.padding.bottom + this.padding.top);
|
||||
|
||||
this.context.resize(width, height);
|
||||
|
||||
this.buffered = true;
|
||||
|
||||
for (const node of this.ChildNodes)
|
||||
{
|
||||
this.DrawChild(
|
||||
this.context,
|
||||
node,
|
||||
width,
|
||||
height
|
||||
);
|
||||
};
|
||||
return this.context;
|
||||
}
|
||||
|
||||
public getContextArea()
|
||||
{
|
||||
return {
|
||||
|
||||
width: Math.min(
|
||||
this.width,
|
||||
this.parentNode?.width || Infinity
|
||||
) - (
|
||||
this.padding.right + this.padding.left
|
||||
),
|
||||
|
||||
height: Math.min(
|
||||
this.height,
|
||||
this.parentNode?.height || Infinity
|
||||
) - (
|
||||
this.padding.bottom + this.padding.top
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
public DrawChild(canvas:CanvasBuffer, node:Node, maxWidth: number, maxHeight: number)
|
||||
{
|
||||
let canvasWidth = Math.min(node.width, maxWidth);
|
||||
let canvasHeight = Math.min(node.height, maxHeight);
|
||||
let x = 0;
|
||||
let y = 0;
|
||||
|
||||
|
||||
node.handleEvent("draw:before",(callback) => {
|
||||
return callback.call(node,{
|
||||
canvasWidth,
|
||||
canvasHeight
|
||||
})
|
||||
});
|
||||
|
||||
if(node.width == 0 || node.height == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
canvasWidth = Math.min(node.width, maxWidth);
|
||||
canvasHeight = Math.min(node.height, maxHeight);
|
||||
|
||||
x += node.x;
|
||||
y += node.y;
|
||||
x += this.padding.left;
|
||||
y += this.padding.top;
|
||||
|
||||
let frame : CanvasBuffer;
|
||||
if(!node.buffered)
|
||||
{
|
||||
frame = node.draw(canvasWidth, canvasHeight);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(node.requiredRedraw)
|
||||
{
|
||||
frame = node.draw(canvasWidth, canvasHeight);
|
||||
}
|
||||
else
|
||||
{
|
||||
frame = node.context as CanvasBuffer;
|
||||
}
|
||||
};
|
||||
let context = canvas.context;
|
||||
context.save();
|
||||
|
||||
if(node.rotate != 0)
|
||||
{
|
||||
let translateX = canvasWidth / 2;
|
||||
let translateY = canvasHeight / 2;
|
||||
|
||||
translateX += x;
|
||||
translateY += y;
|
||||
|
||||
|
||||
context.translate(translateX, translateY);
|
||||
context.rotate(node.rotate);
|
||||
context.translate(-translateX, -translateY);
|
||||
}
|
||||
canvas.writeFrom(
|
||||
frame.offscreen,
|
||||
0,
|
||||
0,
|
||||
frame.offscreen.width,
|
||||
frame.offscreen.height,
|
||||
x,
|
||||
y,
|
||||
frame.offscreen.width * node.scale,
|
||||
frame.offscreen.height * node.scale
|
||||
)
|
||||
node.requiredRedraw = false;
|
||||
context.restore();
|
||||
|
||||
|
||||
node.handleEvent("draw:after",(callback) => {
|
||||
|
||||
return callback.call(this,{
|
||||
canvasWidth,
|
||||
canvasHeight
|
||||
})
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
public isMatchPoint(x:number, y: number)
|
||||
{
|
||||
let {
|
||||
x:realX,
|
||||
y:realY,
|
||||
width:realWidth,
|
||||
height:realheight
|
||||
} = this.realOffset();
|
||||
|
||||
let top = realY;
|
||||
let left = realX;
|
||||
let right = realX + realWidth;
|
||||
let bottom = realY + realheight;
|
||||
if(
|
||||
top < y &&
|
||||
bottom > y &&
|
||||
left < x &&
|
||||
right > x
|
||||
)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected _events : Map<
|
||||
string,
|
||||
(
|
||||
(
|
||||
this:Node,
|
||||
e:NodeEvent
|
||||
) => any
|
||||
)[]
|
||||
> = new Map();
|
||||
|
||||
public on(eventName:string, callback: ((this:Node,e:NodeEvent) => any))
|
||||
{
|
||||
if(this._events.has(eventName))
|
||||
{
|
||||
this._events.get(eventName)?.push(callback);
|
||||
}else{
|
||||
this._events.set(eventName,[callback]);
|
||||
}
|
||||
}
|
||||
public realOffset() : {x:number,y:number,width: number, height: number}
|
||||
{
|
||||
let {
|
||||
width,
|
||||
height
|
||||
} = this.getContextArea();
|
||||
|
||||
if(this.parentNode)
|
||||
{
|
||||
let current : Node = this;
|
||||
let x = 0;
|
||||
let y = 0;
|
||||
while(1)
|
||||
{
|
||||
x += current.x;
|
||||
y += current.y;
|
||||
if(current.parentNode)
|
||||
{
|
||||
current = current.parentNode;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
};
|
||||
return {
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height
|
||||
}
|
||||
}else{
|
||||
let x = this.x;
|
||||
let y = this.y;
|
||||
return {
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height
|
||||
}
|
||||
}
|
||||
}
|
||||
public emit(eventName:string, args: NodeEvent, notifyChild:boolean = true)
|
||||
{
|
||||
let eventList = this._events.get(eventName);
|
||||
|
||||
if(notifyChild)
|
||||
{
|
||||
this.ChildNodes.filter(node => {
|
||||
if(node.isMatchPoint(args.x, args.y))
|
||||
{
|
||||
if(!node.mouseHover)
|
||||
{
|
||||
node.mouseHover = true;
|
||||
let event = args.clone();
|
||||
event.type = "mouse:enter";
|
||||
node.emit("mouse", event, false);
|
||||
};
|
||||
return true
|
||||
}else{
|
||||
if(node.mouseHover)
|
||||
{
|
||||
node.mouseHover = false;
|
||||
let event = args.clone();
|
||||
event.type = "mouse:leave";
|
||||
node.emit("mouse", event);
|
||||
};
|
||||
return false
|
||||
}
|
||||
|
||||
}).some(node => {
|
||||
|
||||
node.emit(eventName, args);
|
||||
return args.prevented != false;
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
if(args.stoppedBubbling == false)
|
||||
{
|
||||
if(eventList)
|
||||
{
|
||||
for (const event of eventList)
|
||||
{
|
||||
event.apply(this, [args]);
|
||||
if(args.prevented)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
public drawScope : Map<string, Function> = new Map();
|
||||
public hasEvent(eventName: string) : boolean
|
||||
{
|
||||
return this.drawScope.has(eventName);
|
||||
}
|
||||
public handleEvent(eventName: string, onCallback?:(callback:Function) => any) : any
|
||||
{
|
||||
let func = this.drawScope.get(eventName);
|
||||
if(func)
|
||||
{
|
||||
if(onCallback)
|
||||
{
|
||||
return onCallback(func);
|
||||
}else{
|
||||
return func.call(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
public handleDraw(e:DrawFunction<this>)
|
||||
{
|
||||
this.drawScope.set("draw", e);
|
||||
}
|
||||
public handleDrawBefore(e:DrawFunction<this>)
|
||||
{
|
||||
this.drawScope.set("draw:before", e);
|
||||
}
|
||||
public handleDrawAfter(e:DrawFunction<this>)
|
||||
{
|
||||
this.drawScope.set("draw:after", e);
|
||||
}
|
||||
public addNode(node:Node)
|
||||
{
|
||||
let {
|
||||
width,
|
||||
height
|
||||
} = this.getContextArea();
|
||||
node.width = node.width || width;
|
||||
node.height = node.height || height;
|
||||
node.parentNode = this;
|
||||
this.ChildNodes.push(node);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
export default class NodeEvent
|
||||
{
|
||||
public type = "";
|
||||
public prevented = false;
|
||||
public stoppedBubbling = false;
|
||||
public data : any = {};
|
||||
public keyCode : number;
|
||||
public key : string;
|
||||
public x : number;
|
||||
public y : number;
|
||||
public clone()
|
||||
{
|
||||
let u = new NodeEvent();
|
||||
u.type = this.type;
|
||||
u.prevented = this.prevented;
|
||||
u.stoppedBubbling = this.stoppedBubbling;
|
||||
u.data = this.data;
|
||||
u.keyCode = this.keyCode;
|
||||
u.key = this.key;
|
||||
u.x = this.x;
|
||||
u.y = this.y;
|
||||
return u;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
html,body{
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Indexed</title>
|
||||
<link rel="stylesheet" href="./index.css">
|
||||
</head>
|
||||
<body>
|
||||
<script src="./index.js"></script>
|
||||
</body>
|
||||
</html>
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,140 @@
|
|||
import Node from "./Compositor/Node";
|
||||
import Canvas from "./Compositor/Canvas"
|
||||
import CanvasBuffer from "./Compositor/CanvasBuffer";
|
||||
|
||||
let container = new Node("Box");
|
||||
container.handleDrawBefore(function(){
|
||||
this.width = 400;
|
||||
this.height = 400;
|
||||
this.padding = {
|
||||
left: 2,
|
||||
right: 2,
|
||||
top: 2,
|
||||
bottom: 2
|
||||
};
|
||||
});
|
||||
|
||||
let scroll = 2;
|
||||
container.handleDraw(function(canvasBuffer,area){
|
||||
let ctx = canvasBuffer.context;
|
||||
ctx.beginPath();
|
||||
ctx.lineWidth = 1;
|
||||
ctx.strokeStyle = "red";
|
||||
ctx.rect(2,2,area.width - 2,area.height - 2);
|
||||
ctx.stroke();
|
||||
ctx.closePath();
|
||||
let offscreen = new CanvasBuffer(area.width - 8, area.height - 8);
|
||||
for (const child of this.ChildNodes)
|
||||
{
|
||||
this.DrawChild(offscreen, child, offscreen.width - 8, offscreen.height - 8);
|
||||
};
|
||||
offscreen.writeTo(
|
||||
ctx,
|
||||
0,0, area.width, area.height,
|
||||
4,4, area.width, area.height
|
||||
);
|
||||
});
|
||||
|
||||
class Button extends Node
|
||||
{
|
||||
public color : string = "#00ff00";
|
||||
constructor(x: number, y:number, name: string){
|
||||
super();
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.name = name;
|
||||
this.handleDrawBefore(function(area){
|
||||
this.width = 50;
|
||||
this.height = 50;
|
||||
});
|
||||
this.handleDraw(function(canvasBuffer,area){
|
||||
let ctx = canvasBuffer.context;
|
||||
ctx.beginPath();
|
||||
ctx.lineWidth = 1;
|
||||
ctx.fillStyle = this.color;
|
||||
ctx.fillRect(0,0,area.width - 4,area.height - 4);
|
||||
ctx.closePath();
|
||||
return true;
|
||||
});
|
||||
this.on("mouse",(event) => {
|
||||
switch(event.type)
|
||||
{
|
||||
case "mouse:down":{
|
||||
event.stoppedBubbling = true;
|
||||
this.color = "#007700";
|
||||
this.update();
|
||||
break;
|
||||
}
|
||||
case "mouse:up":{
|
||||
event.stoppedBubbling = true;
|
||||
this.color = "#00dd00";
|
||||
this.update();
|
||||
break;
|
||||
}
|
||||
case "mouse:enter":{
|
||||
event.stoppedBubbling = true;
|
||||
this.color = "#00dd00";
|
||||
this.update();
|
||||
break;
|
||||
}
|
||||
case "mouse:leave":{
|
||||
event.stoppedBubbling = true;
|
||||
this.color = "#00ff00";
|
||||
this.update();
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
class TextNode extends Node
|
||||
{
|
||||
public color : string = "#00ff00";
|
||||
public textSize: TextMetrics;
|
||||
public text: string;
|
||||
public fontSize : number = 24;
|
||||
constructor(text: string){
|
||||
super();
|
||||
this.text = text;
|
||||
this.context.context.font = "system-ui "+this.fontSize+"px";
|
||||
this.textSize = this.context.context.measureText(text);
|
||||
|
||||
this.handleDrawBefore(function(){
|
||||
this.width = this.textSize.width;
|
||||
this.height = 50;
|
||||
});
|
||||
this.handleDraw(function(canvasBuffer,area){
|
||||
let ctx = canvasBuffer.context;
|
||||
ctx.beginPath();
|
||||
ctx.lineWidth = 1;
|
||||
ctx.fillStyle = this.color;
|
||||
ctx.fillRect(2,2,area.width - 2,area.height - 2);
|
||||
ctx.closePath();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
for(let a = 0; a < 500; a += 50)
|
||||
{
|
||||
for(let b = 0; b < 500; b += 50)
|
||||
{
|
||||
container.addNode(new Button(a,b,"Box A"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let t = new Canvas();
|
||||
t.init();
|
||||
t.addNode(container);
|
||||
|
||||
t.canvas.addEventListener("wheel",function(event){
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
let delta = event.deltaY < 0 ? -5 : +5;
|
||||
|
||||
scroll = Math.max(scroll + delta, 0);
|
||||
|
||||
container.update();
|
||||
|
||||
});
|
Loading…
Reference in New Issue