javascript - Honeycomb hexagonal grid? - Stack Overflow

I'm trying to draw a hexagonal grid in a honeyb shape.So far I'm able to draw it in a rectan

I'm trying to draw a hexagonal grid in a honeyb shape. So far I'm able to draw it in a rectangular shape but I don't know how to convert my for loop to make a honeyb shape instead.

This is what I currently have

<html>

<body>
    <canvas width='1080' height='720' id='hexmap'></canvas>
</body>
<script>

    window.addEventListener('DOMContentLoaded', (event) => {

        var canvas = document.getElementById('hexmap');

    var hexHeight,
        hexRadius,
        hexRectangleHeight,
        hexRectangleWidth,
        hexagonAngle = 0.523598776, // 30 degrees in radians
        sideLength = 36,
        boardWidth = 10,
        boardHeight = 10;

    hexHeight = Math.sin(hexagonAngle) * sideLength;
    hexRadius = Math.cos(hexagonAngle) * sideLength;
    hexRectangleHeight = sideLength + 2 * hexHeight;
    hexRectangleWidth = 2 * hexRadius;
    var ctx = canvas.getContext('2d');

        ctx.fillStyle = "#000000";
        ctx.strokeStyle = "#CCCCCC";
        ctx.lineWidth = 1;

    drawBoard(ctx, boardWidth, boardHeight);
    
    function drawBoard(canvasContext, width, height) {

        var i,j;
        //this loop generates a rectangular hexagon grid
        for(i = 0; i < width; ++i) {
            for(j = 0; j < height; ++j) {
                drawHexagon(
                    ctx, 
                    i * hexRectangleWidth + ((j % 2) * hexRadius), 
                    j * (sideLength + hexHeight), 
                    false
                );
            }
        }
    }

    function drawHexagon(canvasContext, x, y, fill) {           
        var fill = fill || false;

        canvasContext.beginPath();
        canvasContext.moveTo(x + hexRadius, y);
        canvasContext.lineTo(x + hexRectangleWidth, y + hexHeight);
        canvasContext.lineTo(x + hexRectangleWidth, y + hexHeight + sideLength);
        canvasContext.lineTo(x + hexRadius, y + hexRectangleHeight);
        canvasContext.lineTo(x, y + sideLength + hexHeight);
        canvasContext.lineTo(x, y + hexHeight);
        canvasContext.closePath();

        if(fill) {
            canvasContext.fill();
        } else {
            canvasContext.stroke();
        }
    }

})
</script>

</html>

I'm trying to draw a hexagonal grid in a honeyb shape. So far I'm able to draw it in a rectangular shape but I don't know how to convert my for loop to make a honeyb shape instead.

This is what I currently have

<html>

<body>
    <canvas width='1080' height='720' id='hexmap'></canvas>
</body>
<script>

    window.addEventListener('DOMContentLoaded', (event) => {

        var canvas = document.getElementById('hexmap');

    var hexHeight,
        hexRadius,
        hexRectangleHeight,
        hexRectangleWidth,
        hexagonAngle = 0.523598776, // 30 degrees in radians
        sideLength = 36,
        boardWidth = 10,
        boardHeight = 10;

    hexHeight = Math.sin(hexagonAngle) * sideLength;
    hexRadius = Math.cos(hexagonAngle) * sideLength;
    hexRectangleHeight = sideLength + 2 * hexHeight;
    hexRectangleWidth = 2 * hexRadius;
    var ctx = canvas.getContext('2d');

        ctx.fillStyle = "#000000";
        ctx.strokeStyle = "#CCCCCC";
        ctx.lineWidth = 1;

    drawBoard(ctx, boardWidth, boardHeight);
    
    function drawBoard(canvasContext, width, height) {

        var i,j;
        //this loop generates a rectangular hexagon grid
        for(i = 0; i < width; ++i) {
            for(j = 0; j < height; ++j) {
                drawHexagon(
                    ctx, 
                    i * hexRectangleWidth + ((j % 2) * hexRadius), 
                    j * (sideLength + hexHeight), 
                    false
                );
            }
        }
    }

    function drawHexagon(canvasContext, x, y, fill) {           
        var fill = fill || false;

        canvasContext.beginPath();
        canvasContext.moveTo(x + hexRadius, y);
        canvasContext.lineTo(x + hexRectangleWidth, y + hexHeight);
        canvasContext.lineTo(x + hexRectangleWidth, y + hexHeight + sideLength);
        canvasContext.lineTo(x + hexRadius, y + hexRectangleHeight);
        canvasContext.lineTo(x, y + sideLength + hexHeight);
        canvasContext.lineTo(x, y + hexHeight);
        canvasContext.closePath();

        if(fill) {
            canvasContext.fill();
        } else {
            canvasContext.stroke();
        }
    }

})
</script>

</html>
Which results in this shape

What I'd like to achieve though is a shape like this

I was able to do it using like 13 separate for loops, shifting the hexagon over manually each time but it wasn't very practical nor automated.

Share Improve this question asked Apr 20, 2022 at 15:58 KaylaKayla 3231 gold badge3 silver badges16 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 9

If we set some conditions, we can derive an algorithm quite easily. Let the conditions be:

  • width & height have to be equal
  • width & height have to be odd numbers

Now let's look at your shape, which meets the condition as it's width & height is 13. A closer look reveals that we have 7 hexagons in the first row, 8 in the second, 9 in the third and so on up to 13 hexagons at row 7. Afterwards the number of hexagons decreases by one per row until reaching the last row 13.

So the number of hexagons per row can be expressed as:

hexagons = width - (Math.abs(Math.floor(width / 2) - i));

Where i is the row.

Likewise the horizontal starting position of each row decrements by half a hexagon's width until reaching the center.

xStart = (width - 3) % 4 == 0 ? Math.ceil((width - hexagons) / 2) : Math.floor((width - hexagons) / 2);

Now all that's left to do is modifying your for-loop to start at xStart up to xStart+hexagons.

for (j = xStart; j < xStart+hexagons; j++)

Here's a plete example:

var canvas = document.getElementById('hexmap');

var hexHeight,
  hexRadius,
  hexRectangleHeight,
  hexRectangleWidth,
  hexagonAngle = 0.523598776, // 30 degrees in radians
  sideLength = 9,
  boardWidth = 13,
  boardHeight = 13;

hexHeight = Math.sin(hexagonAngle) * sideLength;
hexRadius = Math.cos(hexagonAngle) * sideLength;
hexRectangleHeight = sideLength + 2 * hexHeight;
hexRectangleWidth = 2 * hexRadius;
var ctx = canvas.getContext('2d');

ctx.fillStyle = "#000000";
ctx.strokeStyle = "#CCCCCC";
ctx.lineWidth = 1;

drawBoard(ctx, boardWidth, boardHeight);

function drawBoard(canvasContext, width, height) {
  var i, j, hexagons, xStart;
  //this loop generates a rectangular hexagon grid
  for (i = 0; i < height; i++) {
    hexagons = width - (Math.abs(Math.floor(width / 2) - i));
    xStart = (width - 3) % 4 == 0 ? Math.ceil((width - hexagons) / 2) : Math.floor((width - hexagons) / 2);

    for (j = xStart; j < xStart + hexagons; j++) {
      drawHexagon(
        ctx,
        j * hexRectangleWidth + ((i % 2) * hexRadius),
        i * (sideLength + hexHeight),
        false
      );
    }
  }
}

function drawHexagon(canvasContext, x, y, fill) {
  var fill = fill || false;

  canvasContext.beginPath();
  canvasContext.moveTo(x + hexRadius, y);
  canvasContext.lineTo(x + hexRectangleWidth, y + hexHeight);
  canvasContext.lineTo(x + hexRectangleWidth, y + hexHeight + sideLength);
  canvasContext.lineTo(x + hexRadius, y + hexRectangleHeight);
  canvasContext.lineTo(x, y + sideLength + hexHeight);
  canvasContext.lineTo(x, y + hexHeight);
  canvasContext.closePath();

  if (fill) {
    canvasContext.fill();
  } else {
    canvasContext.stroke();
  }
}

document.getElementById("slider").oninput = (e) => {
  ctx.clearRect(0, 0, canvas.width, canvas.height)
  drawBoard(ctx, e.target.value, e.target.value);
}
<input type="range" min="3" max="27" value="13" step="2" id="slider"><br>
<canvas width='400' height='300' id='hexmap'></canvas>

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744402619a4572464.html

相关推荐

  • javascript - Honeycomb hexagonal grid? - Stack Overflow

    I'm trying to draw a hexagonal grid in a honeyb shape.So far I'm able to draw it in a rectan

    8天前
    20

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信