我在画布上绘制一个等角网格。它使用30度角度偏移,并使用一些脚本来绘制基本的网格。对于这个网格,我投影了一个具有40x40瓷砖大小的平面网格。
gridRows = 10;
gridCols = 10;
tileSize = 40;
gridWidth = gridCols * tileSize;
gridHeight = gridRows * tileSize;
canvasWidth = tileSize * (gridCols + gridRows) * Math.sqrt(3) / 2;
canvasHeight = tileSize * (gridRows + gridCols) / 2;
canvasOffset = tileSize * gridRows * Math.sqrt(3) / 2;
function carToIso(x, y) {
// Convert cartesian (x, y) to isometric coordinates
return [
Math.round((x - y) * Math.sqrt(3) / 2 + canvasOffset),
Math.round((x + y) / 2)
];
}
function drawGrid() {
let canvas = $("#canvas");
canvas.attr('width', canvasWidth);
canvas.attr('height', canvasHeight);
let ctx = canvas.get(0).getContext('2d');
// Background
ctx.fillStyle = "white";
ctx.fillRect(0, 0, canvasWidth, canvasHeight);
// Draw lines
ctx.beginPath();
ctx.lineWidth = 1;
// Rows
for(let i = 0; i <= gridRows; ++i) {
ctx.moveTo(...carToIso(0, i * tileSize));
ctx.lineTo(...carToIso(gridWidth, i * tileSize));
}
// Columns
for(let i = 0; i <= gridCols; ++i) {
ctx.moveTo(...carToIso(i * tileSize, 0));
ctx.lineTo(...carToIso(i * tileSize, gridHeight));
}
ctx.stroke();
}
drawGrid();
这个代码运行良好,可以得到我想要的网格。这里有一个工作范例:https://jsfiddle.net/fgw10sev/2/
接下来,我需要确定用户正在悬停的是哪个小块。最初我有一个2:1的网格,并且能够将画布内的鼠标坐标转换为原始未投影的网格坐标,如下所示:
function mouseToIso(x, y) {
// Convert mouse (x, y in canvas) to grid coordinates
return [
Math.round((2 * y + x - canvasOffset) / 2),
Math.round((2 * y - x + canvasOffset) / 2)
];
}
然而,加入sqrt(3)因子后,原方法失效了,我无法弄清楚如何解决这个问题。原来的mouseToIso函数已经是试错的垃圾代码了,我尝试在不同的地方注入sqrt(3)因子,但我就是无法让它正常工作。
有人可以帮助我吗?或者告诉我需要完全不同的方法吗?
备注:我需要这个sqrt(3)因子,因为我使用的图像都是以30度角度数摆放的,如果没有这个因子,网格就不能正确地与图像对齐。
备注2:仅供完整性说明-sqrt(3)/2 == cos(deg2rad(30)),并且可以互换使用2。
return [ Math.round(((x - canvasOffset) + y * Math.sqrt(3)) / Math.sqrt(3)), Math.round((canvasOffset - x + Math.sqrt(3) * y) / Math.sqrt(3)) ];
基本上是相同的东西,只是减少了一些因素。 - Gerard