我有一个六边形网格,我正在使用具有不同类型值和相应颜色的 HTML 画布绘制。我想将与其他六边形相邻的相同类型的六边形组合起来。这是我当前的功能:
drawGrid() {
lineCtx.clearRect(0, 0, canvas.width, canvas.height);
const size = mapContainer.zoom * 100;
const rect = mapContainer.getViewedHexes();
let hexList = [];
for (let row = rect.top; row < rect.bottom; row++) {
for (let col = rect.left; col < rect.right; col++) {
hexList.push({
points: hexPoints(hexCenter(size, row, col), size, size),
row: row,
col: col,
type: mapContainer.hexGrid[row][col]
});
}
}
//Combine the hexes where they neighbour the same type, the way the hexes are drawn is in the odd-r horizontal layout where the odd rows are shoved right.
hexList.forEach(hex => {
this.drawPolygon(hex.points, "rgba(255,0,0, 0.4)");
});
}
也可以随意批评我的 javascript 代码,因为我还有很多东西要学。
这些是我用来创建十六进制网格的一些函数,如果你想看的话:
function hexPoints(center, height, width) {
const points = [];
for (let i = 0 ; i < 6 ; i++) {
points[i] = hexCorner(center, height / 2, width / 2, i);
}
//Point 0 is the top right corner
//Point 1 is the bottom right corner
//Point 2 is the bottom middle corner
//Point 3 is the bottom left corner
//Point 4 is the top left corner
//Point 5 is the top middle corner
return points;
}
function hexCorner(center, height, width, i) {
const angleDeg = 60 * i - 30;
const angleRad = Math.PI / 180 * angleDeg;
const x = center.x + width * Math.cos(angleRad);
const y = center.y + height * Math.sin(angleRad);
return { x, y };
}
function hexCenter(size, row, col) {
let offset = 0;
if (row % 2 === 1) {
offset = Math.sqrt(3) * size / 4
}
const w = Math.sqrt(3) * size / 2;
const h = 3/2 * size / 2;
const x = w * col + offset + w / 2 + mapContainer.mapX;
const y = h * row + h / (3/2) + mapContainer.mapY;
return {
x: x,
y: y
};
}
所以你想“视觉上”合并?然后简单地跳过抚摸路径。
const ctx = document.querySelector('#grid').getContext('2d');
const TAU = 2 * Math.PI;
const EDGES = 6;
const mapContainer = {
hexGrid: [
[0, 1, 1, 1, 0],
[1, 2, 2, 2, 1],
[1, 2, 2, 2, 1],
[1, 1, 2, 1, 1],
[0, 0, 1, 0, 0]
],
zoom: 0.25,
getViewedHexes: function() {
return {
top: 0,
left: 0,
bottom: 5,
right: 5
};
}
};
drawGrid();
// Based on: https://stackoverflow.com/a/72663019/1762224
function drawGrid() {
const size = Math.floor(mapContainer.zoom * 100);
const rect = mapContainer.getViewedHexes();
const dimensions = getDimensions(size);
const points = hexPoints(size);
for (let gy = rect.top; gy < rect.bottom - rect.top; gy++) {
for (let gx = rect.left; gx < rect.right - rect.left; gx++) {
const color = typeToColor(mapContainer.hexGrid[gy][gx]);
ctx.fillStyle = color;
ctx.strokeStyle = color;
drawPolygon(hexCenter(gx, gy, size), points);
}
}
}
function typeToColor(type) {
switch (type) {
case 1:
return 'grey';
case 2:
return 'yellow';
case 0:
default:
return 'white';
}
}
function hexCenter(gx, gy, size) {
const { grid } = getDimensions(size);
return {
x: (gx + 1) * grid.space.x,
y: (gy + 1) * grid.space.y + (gx % 2 ? grid.offset.y : 0)
};
}
function drawPolygon(p, points) {
ctx.setTransform(1, 0, 0, 1, p.x, p.y);
const [{ x: startX, y: startY }] = points;
ctx.beginPath();
ctx.moveTo(startX, startY);
points.forEach(({ x, y }) => {
ctx.lineTo(x, y);
});
ctx.closePath();
ctx.stroke();
ctx.fill();
}
function hexPoints(size, sides = EDGES, points = []) {
const step = TAU / sides;
let ang = 0, i = sides;
while (i--) {
points.push(toPoint(size * Math.cos(ang), size * Math.sin(ang)));
ang += step;
}
return points;
}
function getDimensions(radius, edges = EDGES) {
const
edgeLength = Math.sin(Math.PI / edges) * radius * 2,
gridSpaceX = radius * 2 - edgeLength * 0.5,
gridSpaceY = Math.cos(Math.PI / edges) * radius * 2,
gridOffsetY = gridSpaceY * 0.5;
return {
edgeLength,
grid: {
space: {
x: gridSpaceX,
y: gridSpaceY
},
offset: {
y: gridOffsetY
}
}
};
}
function toPoint(x, y) {
return ({ x, y });
}
#grid { border: 1px solid #000000; }
<canvas id="grid" width="260" height="260"></canvas>