您可以将网格视为插槽:
0 1 2
|---|---|---|
0 | | | |
|---|---|---|
1 | | | |
|---|---|---|
使用Math.random() 乘以列/行数和Math.floor 来获得一个随机槽位置,在此位置您可以使用splice(random_slot, 2) 数组方法获得槽的边界。
有了手中的边界,你可以简单地减去矩形的大小,你就会得到生成区域,通过一些随机的数学,你可以在这个边界的任何地方生成矩形,而且你永远不会碰到线
水平数学示例:
columns = 20, 50, 270
[0, ...columns, c.width] = [0, 20, 50, 270, width]
random_slot = 2
splice(random_slot, 2) = [50, 270]
deduce rect.width of 270 to never touch right line = [50, 270 - 40]
add and remove pixels to never touch lines = [50 + 2, 230 - 2]
final horizontal bounds = [52, 282]
apply same logic to vertical bounds
最终代码:
var c = document.getElementById("myCanvas");
c.width = 300;
c.height = 150;
var ctx = c.getContext("2d");
ctx.beginPath();
// rectangle size
const rect = [40, 25];
const columns = [100, 200];
const lines = [75];
// draw grid lines
columns.forEach(col => {
ctx.moveTo(col, 0);
ctx.lineTo(col, c.height);
});
lines.forEach(line => {
ctx.moveTo(0, line);
ctx.lineTo(c.width, line);
});
// choose a random slot
const slot = {
x: Math.floor((columns.length + 1) * Math.random()),
y: Math.floor((lines.length + 1) * Math.random())
};
// create bounds to spawn point
const bounds = {
horizontal: [0, ...columns, c.width].splice(slot.x, 2),
vertical: [0, ...lines, c.height].splice(slot.y, 2)
};
// add and remove some pixels to never touch the lines
bounds.horizontal[0] += 2;
bounds.vertical[0] += 2;
bounds.horizontal[1] -= rect[0] + 2;
bounds.vertical[1] -= rect[1] + 2;
ctx.rect(
bounds.horizontal[0] + (bounds.horizontal[1] - bounds.horizontal[0]) * Math.random(),
bounds.vertical[0] + (bounds.vertical[1] - bounds.vertical[0]) * Math.random(),
rect[0],
rect[1]
);
ctx.stroke();
<!DOCTYPE html>
<html>
<body>
<canvas id="myCanvas" width="300" height="150" style="border:1px solid #d3d3d3;">
</canvas>
</body>
</html>
使用 150 次迭代和 5 像素线的距离进行测试: