var ImageWidth = 960
var ImageHeight = 540
var direction1 = "x";
var direction2 = "y";
var vert = true;
var LargeVerticalBoxes = parseInt(document.getElementById("lvb").value);
var inner = parseInt(document.getElementById("inner").value);
var smallest = parseInt(document.getElementById("smallest").value);
var totalboxes = "";
var clickBoxWidth = 200;
var clickBoxHeight = 100;
var lineWidth = 5;
var clickBox_xStart = 0;
var clickBox_yStart = 0;
var minSize = 0.1
var maxSize = 0.9
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
ctx.canvas.width = ImageWidth;
ctx.canvas.height = ImageHeight;
updateSettings();
canvas.addEventListener('click', function(evt) {
var mousePos = getMousePos(canvas, evt);
clearCanvas();
ctx.beginPath();
calcclickBox(mousePos.x, mousePos.y)
ctx.rect(clickBox_xStart, clickBox_yStart, clickBoxWidth, clickBoxHeight);
ctx.lineWidth = lineWidth;
ctx.strokeStyle = 'black';
ctx.stroke();
ctx.closePath();
reDraw();
}, false);
download_img = function(el) {
var image = canvas.toDataURL("image/png");
el.href = image;
};
function updateSettings() {
lineWidth = parseInt(document.getElementById("linewidth").value,10);
clickBoxWidth = parseInt(document.getElementById("boxWidth").value,10);
clickBoxHeight = parseInt(document.getElementById("boxHeight").value,10);
canvas.width = parseInt(document.getElementById("canWidth").value,10);
canvas.height = parseInt(document.getElementById("canHeight").value,10);
document.getElementById("dispW").innerText = "Width: " + canvas.width;
document.getElementById("dispH").innerText = "Height: " + canvas.height;
document.getElementById("canW").innerText = "Width: " + clickBoxWidth;
document.getElementById("canH").innerText = "Height: " + clickBoxHeight;
}
function clearCanvas() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
function calcclickBox(x, y) {
clickBox_xStart = x - clickBoxWidth / 2;
clickBox_yStart = y - clickBoxHeight / 2;
clickBoxWidth = clickBoxWidth;
clickBoxHeight = clickBoxHeight;
}
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
function toggle() {
vert = !vert;
if (vert) {
direction1 = "x";
direction2 = "y";
} else {
direction1 = "y";
direction2 = "x";
}
}
function getTotal() {
LargeVerticalBoxes = parseInt(document.getElementById("lvb").value);
inner = parseInt(document.getElementById("inner").value);
smallest = parseInt(document.getElementById("smallest").value);
totalboxes = LargeVerticalBoxes * inner * smallest * 4 + 1
document.getElementById("total").innerText = totalboxes
}
function getRandomArbitrary(min, max) {
return Math.random() * (max - min) + min;
}
function reDraw() {
getTotal();
let splitDimension = (l, n) => {
let splits = [];
let remaining = l;
let x = 0;
for (let i = 0; i < n - 1; i++) {
let r = Math.random();
let seg = remaining * (1 / n);
let s = seg + 0.75 * (0.5 - r) * seg
splits.push([x, s]);
x += s;
remaining -= s;
}
splits.push([x, remaining])
return splits;
};
class Box {
constructor(x, y, w, h) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.boxes = [];
}
draw(ctx) {
ctx.beginPath();
ctx.rect(this.x, this.y, this.w, this.h);
ctx.stroke();
this.boxes.forEach(box => {
box.draw(ctx)
});
}
addBoxes(n, dim) {
let splits;
if (dim == "x") {
splits = splitDimension(this.w, n)
this.boxes = splits.map(([x, w]) => {
return new Box(this.x + x, this.y, w, this.h)
});
} else {
splits = splitDimension(this.h, n);
this.boxes = splits.map(([y, h]) => {
return new Box(this.x, this.y + y, this.w, h);
})
}
}
}
let TopRightBox = new Box(clickBox_xStart,
clickBox_yStart,
canvas.width - clickBox_xStart,
-clickBox_yStart);
let BottomRight = new Box(clickBox_xStart + clickBoxWidth,
clickBox_yStart,
canvas.width - clickBox_xStart - clickBoxWidth,
canvas.height - clickBox_yStart);
let BottomLeft = new Box(clickBox_xStart + clickBoxWidth,
clickBox_yStart + clickBoxHeight,
-clickBox_xStart - clickBoxWidth,
canvas.height - clickBox_yStart - clickBoxHeight);
let TopLeft = new Box(0, 0, clickBox_xStart, clickBox_yStart + clickBoxHeight);
TopRightBox.addBoxes(LargeVerticalBoxes, direction1);
BottomRight.addBoxes(LargeVerticalBoxes, direction1);
BottomLeft.addBoxes(LargeVerticalBoxes, direction1);
TopLeft.addBoxes(LargeVerticalBoxes, direction1);
TopRightBox.boxes.forEach(box => {
box.addBoxes(inner, direction2);
box.boxes.forEach(boxBox => {
boxBox.addBoxes(smallest, direction1);
});
});
BottomRight.boxes.forEach(box => {
box.addBoxes(inner, direction2);
box.boxes.forEach(boxBox => {
boxBox.addBoxes(smallest, direction1);
});
});
BottomLeft.boxes.forEach(box => {
box.addBoxes(inner, direction2);
box.boxes.forEach(boxBox => {
boxBox.addBoxes(smallest, direction1);
});
});
TopLeft.boxes.forEach(box => {
box.addBoxes(inner, direction2);
box.boxes.forEach(boxBox => {
boxBox.addBoxes(smallest, direction1);
});
});
TopRightBox.draw(ctx);
BottomRight.draw(ctx);
BottomLeft.draw(ctx);
TopLeft.draw(ctx);
document.getElementById("total").innerText = totalboxes
}
<html>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
<style>
canvas {
}
</style>
<body>
<div class="fluid-container px-3 border">
<strong>click</strong> on the canvas to create start box and draw new layout
<div class="row">
<div class="col">
<div class="row">
<div class="col-12">
Canvas:
</div>
</div>
<div class="row">
<div class="col">
<span id="dispW">Width: </span> <input class="form-control" type="range" min="16" max="1920" value=480 id="canWidth" onchange="updateSettings()" />
</div>
<div class="col">
<span id="dispH">Height: </span><input class="form-control" type="range" min="9" max="1080" value=270 id="canHeight" onchange="updateSettings()" />
</div>
</div>
<div class="row">
<div class="col-12">
Start Box:
</div>
</div>
<div class="row">
<div class="col">
<span id="canW">Width: </span> <input class="form-control" type="range" min="1" max="200" value=50 id="boxWidth" onchange="updateSettings()">
</div>
<div class="col">
<span id="canH">Height: </span> <input class="form-control" type="range" min="1" max="200" value=100 id="boxHeight" onchange="updateSettings()">
</div>
</div>
<div class="row">
<div class="col-12">
Line Width: (changing these settings breaks stuff)
<input class="form-control" type="range" min="1" max="20" value="5" id="linewidth" onchange="updateSettings()"> </div>
</div>
<div class="row">
<div class="col-6">
<p>Large Vertical Boxes:
<input type="range" min="1" max="10" value="1" id="lvb" onchange="getTotal()"></p>
<p>Medium inner Boxes:
<input type="range" min="1" max="10" value="1" id="inner" onchange="getTotal()"></p>
<p>Smallest inner Boxes:
<input type="range" min="1" max="10" value="1" id="smallest" onchange="getTotal()">
</p>
</div>
<div class="col-6">
toggle horizontal/vertical
<label class="switch">
<input type="checkbox" id="toggle" onchange="toggle()">
<span class="slider round"></span>
</label>
<p>Total number of boxes: <span id="total"> </span></p>
<a id="download" download="GridLayout.png" href="" onclick="download_img(this);"><button>
Save Layout
</button></a>
</div>
</div>
<br>
<div class="row">
<div class="col">
<canvas id="myCanvas" width="578" height="200" style="border:1px solid #000000;" ></canvas>
</div>
</div>
</div>
</div>
</div>
<br><br><br><br><br>
</body>
</html>