使用 canvas Html & JavaScript 绘制六边形网格

没关系

我尝试使用六边形创建一个大小为 X * X 的画布,目前我基于此参考,并进行了一些修改,到目前为止我的代码如下所示:

const canvas = document.getElementById('canvas');
const context = canvas.getContext('2d');

const shapeType = 6;
const angle = 2 * Math.PI / shapeType;
const radius = 20;

function init() {
    drawGrid(5);
}

init();

function drawGrid(size) {
    for (let y = radius, i = 0; i < size; i++) {
        y += radius * Math.sin(angle);
        for (let x = radius, j = 0;
             j < size;
             x += radius * (1 + Math.cos(angle)), y += (-1) ** j++ * radius * Math.sin(angle)) {
            drawHexagon(x, y);
        }
    }
}

function drawHexagon(x, y) {
    context.beginPath();
    for (let i = 0; i < shapeType; i++) {
        let xx = x + radius * Math.cos(angle * i);
        let yy = y + radius * Math.sin(angle * i);
        context.lineTo(xx, yy);
    }
    context.closePath();
    context.stroke();
}
<!DOCTYPE HTML>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>HexGrid</title>
    <style>
        .test {
            display: flex;
            justify-content: space-between;
        }

        .canvas {
            border: 1px solid #000000;
        }
    </style>
</head>
<body>
<canvas id="canvas" width="500" height="500" class="canvas"></canvas>
<script src="main.js"></script>
</body>
</html>

到目前为止,一切都很好,但只是奇数大小,但如果大小是偶数,我得到这个:

均匀网格

作为JavaScript的初学者,我被阻止了,有人知道我该如何解决这个问题吗?

盲人67

正六边形网格

六边形网格具有规则的间距,就像正方形网格一样,但是如果偏移(在这种情况下向下)为六边形高度的一半,则每隔一列。

得到x和y网格间距,偏移量为y网格间距的一半。

    RADIUS = 20;
    EDGE_LEN = Math.sin(Math.PI / 6) * RADIUS * 2;
    GRID_Y_SPACE = Math.cos(Math.PI / 6) * RADIUS * 2;
    GRID_X_SPACE = RADIUS * 2 - EDGE_LEN * 0.5;
    GRID_Y_OFFSET = GRID_Y_SPACE * 0.5;

可以使用(gx,gy 是列,行位置)计算六边形的位置

    function gridToPixel(gx, gy, p = {}) {
        p.x = gx * GRID_X_SPACE;
        p.y = gy * GRID_Y_SPACE + (gx % 2 ? GRID_Y_OFFSET : 0);        
        return p;
    }

例子

示例用六边形网格填充画布。

const ctx = canvas.getContext('2d');

const P2 = (x, y) => ({x,y});
const EDGES = 6;
const RADIUS = 20;
const TAU = 2 * Math.PI;
const EDGE_LEN = Math.sin(Math.PI / EDGES) * RADIUS * 2;
const GRID_Y_SPACE = Math.cos(Math.PI / EDGES) * RADIUS * 2;
const GRID_X_SPACE = RADIUS * 2 - EDGE_LEN * 0.5;
const GRID_Y_OFFSET = GRID_Y_SPACE * 0.5;

drawGrid(1, 1, 15, 13, createPoly(EDGES));
function drawGrid(x, y, w, h, points) {
  const p = P2();
  var gy, gx;
  ctx.beginPath();
  for (gy = y; gy < y + h; gy++) {
      for (gx = x; gx < x + w; gx++) {
          addPoly(gridToPixel(gx, gy, p), points);
      }
  }
  ctx.stroke();
}
function gridToPixel(gx, gy, p = {}) {
    p.x = gx * GRID_X_SPACE;
    p.y = gy * GRID_Y_SPACE + (gx % 2 ? GRID_Y_OFFSET : 0);       
    return p;
}
function addPoly(p, points) { // p.x, p.y is center
    ctx.setTransform(1, 0, 0, 1, p.x, p.y);
    var i = 0;
    const p2 = points[i++];
    ctx.moveTo(p2.x, p2.y);
    while (i < points.length) {
        const p2 = points[i++];
        ctx.lineTo(p2.x, p2.y);
    }
    ctx.closePath();
}
function createPoly(sides, points = []) {
    const step = TAU / sides;
    var ang = 0, i = sides;
    while (i--) {
        points.push(P2(RADIUS * Math.cos(ang), RADIUS * Math.sin(ang)));
        ang += step;
    }
    return points;
}
canvas { border: 1px solid #000000; }
<canvas id="canvas" width="500" height="500"></canvas>

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章