Layouting Algorithm
by egon
HTML
<canvas id="view"></canvas>
<script src="main.js"></script>
CSS
#view { background: #fff; }
body, html { background: #444; width: 100%; height: 100%; margin: 0px;}
JavaScript
var view = document.getElementById("view");
var context = view.getContext("2d");
var area = R(0,0,640,480).insetBy(5);
function rcolor(lightness){
return 'hsla(' + (Math.random()*360|0) + ',70%,' + (lightness||70) + '%,0.8)';
}
function R(left, top, right, bottom){
return {
left:left, top:top||left, right:right||left, bottom:bottom||top||left,
clone: function(){ return R(this.left, this.top, this.right, this.bottom); },
get width(){ return this.right - this.left; },
get height(){ return this.bottom - this.top; },
get size(){ return {x: this.width, y: this.height}},
// inset/outset by a single value
insetBy: function(v){
return R(this.left + v, this.top + v, this.right - v, this.bottom - v);
},
outsetBy: function(v){ return insetBy(-v); },
// inset explicitly each side
inset: function(sides){
return R(this.left + sides.left, this.top + sides.top, this.right - sides.right, this.bottom - sides.bottom);
},
outset: function(sides){
return R(this.left - sides.left, this.top - sides.top, this.right + sides.right, this.bottom + sides.bottom);
},
offset: function(p){
return R(this.left + p.x, this.top + p.y, this.right + p.x, this.bottom + p.y);
},
stroke: function(context, color, lineWidth){
context.lineWidth = lineWidth || 2;
context.strokeStyle = color;
context.beginPath();
context.rect(this.left, this.top, this.right - this.left, this.bottom - this.top);
context.closePath();
context.stroke();
},
fill: function(context, color){
context.fillStyle = color;
context.fillRect(this.left, this.top, this.right - this.left, this.bottom - this.top);
},
toString: function(){
return "[" + [this.left,this.top,this.right,this.bottom].join(", ") + "]";
}
};
}
function NewBlock(name, opts, children){
var b = {
name: name,
color: rcolor(),
size: { x:"100%", y:"100%" },
position: "center",
...