Padding calculation

This commit is contained in:
Abdussamed 2023-06-11 17:44:05 +03:00
parent 635ece9755
commit 7da0710e74
7 changed files with 269 additions and 372 deletions

View File

@ -154,6 +154,11 @@ function _draw_content_to_canvas(
dheight?:number
)
{
if(
canvas.width != 0 && canvas.height != 0 &&
context.canvas.width != 0 && context.canvas.height != 0
)
{
context.drawImage(
canvas,
x || 0,
@ -165,4 +170,5 @@ function _draw_content_to_canvas(
dwidth || canvas.width,
dheight || canvas.height
)
};
}

48
Compositor/ImageNode.ts Normal file
View File

@ -0,0 +1,48 @@
import Node from "./Node"
export default class ImageNode extends Node
{
public image? : CanvasImageSource;
public backgroundColor : string = "rgba(0,0,0,0)";
public constructor(){
super();
this.handleDrawBefore(()=>{
if(this.width == 0)
{
this.width = (this.image?.width || 0) as number;
this.height = (this.image?.height || 0) as number;
}
});
this.handleDraw(function(ctx,area){
if(this.image && this.image.width)
{
ctx.context.fillStyle = this.backgroundColor;
ctx.context.fillRect(0,0,area.width,area.height)
ctx.context.drawImage(
this.image,
0,
0,
this.image.width as number,
this.image.height as number,
0,
0,
area.width,
area.height
)
};
return true;
})
}
public loadFromURL(url:string)
{
this.image = new Image();
this.image.onload = () => {
this.update();
};
this.image.src = url;
}
public loadFromImage(image:CanvasImageSource)
{
this.image = image;
}
};

View File

@ -49,6 +49,7 @@ export default class Node
}
public draw(maxWidth?: number, maxHeight?: number) : CanvasBuffer
{
this.context.clear();
let drawableAreaWidth = this.width;
let drawableAreaHeight = this.height;
@ -292,6 +293,8 @@ export default class Node
y += current.y;
if(current.parentNode)
{
x += current.parentNode.padding.left;
y += current.parentNode.padding.top;
current = current.parentNode;
}
else

31
Compositor/TextNode.ts Normal file
View File

@ -0,0 +1,31 @@
import Node from "./Node";
export default class TextNode extends Node
{
public color : string = "#000000";
public text: string;
public fontSize : number = 18;
constructor(text: string){
super();
this.text = text;
this.handleDrawBefore(function(){
this.height = this.fontSize;
this.context.context.save();
this.context.context.font = this.fontSize+"px system-ui";
this.width = this.context.context.measureText(this.text).width;
this.context.context.restore();
console.log(this.width)
});
this.handleDraw(function(canvasBuffer,area){
let ctx = canvasBuffer.context;
ctx.font = this.fontSize+"px system-ui";
ctx.beginPath();
ctx.fillStyle = this.color;
ctx.textAlign = 'left';
ctx.textBaseline = 'top';
ctx.fillText(this.text, 0,0);
ctx.closePath();
});
}
};

388
index.js
View File

@ -575,123 +575,140 @@ function hmrAccept(bundle /*: ParcelRequire */ , id /*: string */ ) {
},{}],"1jwFz":[function(require,module,exports) {
var parcelHelpers = require("@parcel/transformer-js/src/esmodule-helpers.js");
var _node = require("./Compositor/Node");
var _nodeDefault = parcelHelpers.interopDefault(_node);
var _canvas = require("./Compositor/Canvas");
var _canvasDefault = parcelHelpers.interopDefault(_canvas);
let container = new (0, _nodeDefault.default)("Box");
container.handleDrawBefore(function() {
this.width = 400;
this.height = 400;
this.padding = {
left: 10,
right: 10,
top: 10,
bottom: 10
};
});
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
)*/ return true;
});
class Button extends (0, _nodeDefault.default) {
constructor(x, y, name){
super();
this.color = "#00ff00";
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 (0, _nodeDefault.default) {
constructor(text){
super();
this.color = "#00ff00";
this.fontSize = 24;
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"));
var _textNode = require("./Compositor/TextNode");
var _textNodeDefault = parcelHelpers.interopDefault(_textNode);
let t = new (0, _canvasDefault.default)();
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();
});
let text = new (0, _textNodeDefault.default)("Merhaba arkadaşlar nasılsınız ?");
text.color = "black";
text.x = 0;
text.fontSize = 24;
text.y = 0;
t.addNode(text);
},{"./Compositor/Node":"a8tDl","./Compositor/Canvas":"lKBnk","@parcel/transformer-js/src/esmodule-helpers.js":"7Rzro"}],"a8tDl":[function(require,module,exports) {
},{"./Compositor/Canvas":"lKBnk","@parcel/transformer-js/src/esmodule-helpers.js":"7Rzro","./Compositor/TextNode":"3dGtM"}],"lKBnk":[function(require,module,exports) {
var parcelHelpers = require("@parcel/transformer-js/src/esmodule-helpers.js");
parcelHelpers.defineInteropFlag(exports);
var _node = require("./Node");
var _nodeDefault = parcelHelpers.interopDefault(_node);
var _nodeEvent = require("./NodeEvent");
var _nodeEventDefault = parcelHelpers.interopDefault(_nodeEvent);
class Canvas {
constructor(){
this.rootNode = new (0, _nodeDefault.default)("Root");
this.nodes = [];
this.pool = new DrawPool();
this.canvas = document.createElement("canvas");
this.context = this.canvas.getContext("2d");
this.installMouseManager();
this.installKeyboardManager();
}
init() {
this.canvas.style.imageRendering = "pixelated";
window.document.body.appendChild(this.canvas);
this.recalculateSize();
window.addEventListener("resize", ()=>this.recalculateSize());
this.pool.trigger = ()=>this.drawContext();
}
installMouseManager() {
this.canvas.addEventListener("mousedown", (event)=>{
let mouseEvent = new (0, _nodeEventDefault.default)();
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 (0, _nodeEventDefault.default)();
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 (0, _nodeEventDefault.default)();
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 (0, _nodeEventDefault.default)();
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 (0, _nodeEventDefault.default)();
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);
});
}
installKeyboardManager() {}
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();
}
addNode(node, priority = 0) {
this.nodes.push([
node,
priority
]);
node.on("draw", ()=>{
this.pool.notify();
});
this.pool.notify();
}
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);
}
}
exports.default = Canvas;
class DrawPool {
addPool(e) {
if (!this.busy) this.notify();
else this.trigger = e;
}
notify() {
this.busy = true;
this.inf = requestAnimationFrame(()=>{
if (this.trigger) this.trigger();
this.busy = false;
});
}
constructor(){
this.busy = true;
this.inf = -1;
}
}
},{"./Node":"a8tDl","./NodeEvent":"9Fl2V","@parcel/transformer-js/src/esmodule-helpers.js":"7Rzro"}],"a8tDl":[function(require,module,exports) {
var parcelHelpers = require("@parcel/transformer-js/src/esmodule-helpers.js");
parcelHelpers.defineInteropFlag(exports);
var _canvasBuffer = require("./CanvasBuffer");
@ -728,6 +745,7 @@ class Node {
else this.emit("draw", new (0, _nodeEventDefault.default)(), false);
}
draw(maxWidth, maxHeight) {
this.context.clear();
let drawableAreaWidth = this.width;
let drawableAreaHeight = this.height;
if (maxWidth) drawableAreaWidth = Math.min(drawableAreaWidth, maxWidth);
@ -840,8 +858,11 @@ class Node {
while(true){
x += current.x;
y += current.y;
if (current.parentNode) current = current.parentNode;
else break;
if (current.parentNode) {
x += current.parentNode.padding.left;
y += current.parentNode.padding.top;
current = current.parentNode;
} else break;
}
return {
x,
@ -983,7 +1004,7 @@ class CanvasBuffer {
}
exports.default = CanvasBuffer;
function _draw_content_to_canvas(context, canvas, x, y, width, height, dx, dy, dwidth, dheight) {
context.drawImage(canvas, x || 0, y || 0, width || canvas.width, height || canvas.height, dx || 0, dy || 0, dwidth || canvas.width, dheight || canvas.height);
if (canvas.width != 0 && canvas.height != 0 && context.canvas.width != 0 && context.canvas.height != 0) context.drawImage(canvas, x || 0, y || 0, width || canvas.width, height || canvas.height, dx || 0, dy || 0, dwidth || canvas.width, dheight || canvas.height);
}
},{"@parcel/transformer-js/src/esmodule-helpers.js":"7Rzro"}],"7Rzro":[function(require,module,exports) {
@ -1041,126 +1062,39 @@ class NodeEvent {
}
exports.default = NodeEvent;
},{"@parcel/transformer-js/src/esmodule-helpers.js":"7Rzro"}],"lKBnk":[function(require,module,exports) {
},{"@parcel/transformer-js/src/esmodule-helpers.js":"7Rzro"}],"3dGtM":[function(require,module,exports) {
var parcelHelpers = require("@parcel/transformer-js/src/esmodule-helpers.js");
parcelHelpers.defineInteropFlag(exports);
var _node = require("./Node");
var _nodeDefault = parcelHelpers.interopDefault(_node);
var _nodeEvent = require("./NodeEvent");
var _nodeEventDefault = parcelHelpers.interopDefault(_nodeEvent);
class Canvas {
constructor(){
this.rootNode = new (0, _nodeDefault.default)("Root");
this.nodes = [];
this.pool = new DrawPool();
this.canvas = document.createElement("canvas");
this.context = this.canvas.getContext("2d");
this.installMouseManager();
this.installKeyboardManager();
}
init() {
this.canvas.style.imageRendering = "pixelated";
window.document.body.appendChild(this.canvas);
this.recalculateSize();
window.addEventListener("resize", ()=>this.recalculateSize());
this.pool.trigger = ()=>this.drawContext();
}
installMouseManager() {
this.canvas.addEventListener("mousedown", (event)=>{
let mouseEvent = new (0, _nodeEventDefault.default)();
mouseEvent.x = event.offsetX;
mouseEvent.y = event.offsetY;
mouseEvent.type = "mouse:down";
this.rootNode.emit("mouse", mouseEvent);
class TextNode extends (0, _nodeDefault.default) {
constructor(text){
super();
this.color = "#000000";
this.fontSize = 18;
this.text = text;
this.handleDrawBefore(function() {
this.height = this.fontSize;
this.context.context.save();
this.context.context.font = this.fontSize + "px system-ui";
this.width = this.context.context.measureText(this.text).width;
this.context.context.restore();
console.log(this.width);
});
this.canvas.addEventListener("mousemove", (event)=>{
let mouseEvent = new (0, _nodeEventDefault.default)();
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.handleDraw(function(canvasBuffer, area) {
let ctx = canvasBuffer.context;
ctx.font = this.fontSize + "px system-ui";
ctx.beginPath();
ctx.fillStyle = this.color;
ctx.textAlign = "left";
ctx.textBaseline = "top";
ctx.fillText(this.text, 0, 0);
ctx.closePath();
});
this.canvas.addEventListener("mouseup", (event)=>{
let mouseEvent = new (0, _nodeEventDefault.default)();
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 (0, _nodeEventDefault.default)();
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 (0, _nodeEventDefault.default)();
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);
});
}
installKeyboardManager() {}
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();
}
addNode(node, priority = 0) {
this.nodes.push([
node,
priority
]);
node.on("draw", ()=>{
this.pool.notify();
});
this.pool.notify();
}
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);
}
}
exports.default = Canvas;
class DrawPool {
addPool(e) {
if (!this.busy) this.notify();
else this.trigger = e;
}
notify() {
this.busy = true;
this.inf = requestAnimationFrame(()=>{
if (this.trigger) this.trigger();
this.busy = false;
});
}
constructor(){
this.busy = true;
this.inf = -1;
}
}
exports.default = TextNode;
},{"./Node":"a8tDl","./NodeEvent":"9Fl2V","@parcel/transformer-js/src/esmodule-helpers.js":"7Rzro"}]},["3beyG","1jwFz"], "1jwFz", "parcelRequire94c2")
},{"./Node":"a8tDl","@parcel/transformer-js/src/esmodule-helpers.js":"7Rzro"}]},["3beyG","1jwFz"], "1jwFz", "parcelRequire94c2")
//# sourceMappingURL=index.js.map

File diff suppressed because one or more lines are too long

141
index.ts
View File

@ -1,142 +1,17 @@
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: 10,
right: 10,
top: 10,
bottom: 10
};
});
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
)*/
return true;
});
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"));
}
}
import ImageNode from "./Compositor/ImageNode";
import TextNode from "./Compositor/TextNode";
let t = new Canvas();
t.init();
t.addNode(container);
t.canvas.addEventListener("wheel",function(event){
event.preventDefault();
event.stopPropagation();
let text = new TextNode("Merhaba arkadaşlar nasılsınız ?");
text.color = "black";
text.x = 0;
text.fontSize = 24;
text.y = 0;
let delta = event.deltaY < 0 ? -5 : +5;
scroll = Math.max(scroll + delta, 0);
container.update();
});
t.addNode(text);