使用HTML Canvas与JavaScript绘制六边形网格偶数尺寸错位问题
问题原因
偶数尺寸下网格错位的核心问题是drawGrid函数的变量作用域逻辑错误:内层绘制单个六边形的循环直接修改了外层控制行位置的y变量。
当一行绘制的六边形数量为偶数时,内层循环结束后y值的累计偏移没有归零,外层循环进入下一行时,会在这个错误的y值基础上累加行高,直接导致后续所有行的起始位置偏移,出现排列错位。奇数尺寸下刚好偏移量抵消,所以看起来表现正常,但逻辑本身存在隐患。
修复方案
调整drawGrid的坐标计算逻辑,每一行的基准坐标单独计算存储,内层循环只读取基准值计算单个六边形位置,不修改外层的行坐标变量,从根源上避免坐标污染。
修复后的完整JS代码如下:
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(6); // 传入偶数测试也不会错位 } init(); function drawGrid(size) { // 预计算六边形固定尺寸参数 const hexHalfHeight = radius * Math.sin(angle); const hexRowHeight = 2 * hexHalfHeight; const hexHorizontalStep = radius * (1 + Math.cos(angle)); const oddRowXOffset = radius + radius * Math.cos(angle); for (let i = 0; i < size; i++) { // 固定当前行的基准坐标,内层循环不修改这两个值 const currentRowY = radius + i * hexRowHeight; const currentRowBaseX = radius + (i % 2 === 1 ? oddRowXOffset : 0); for (let j = 0; j < size; j++) { const x = currentRowBaseX + j * hexHorizontalStep; drawHexagon(x, currentRowY); } } } 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(); }
对应的HTML部分不需要做任何修改,保持原有代码即可。
修改点说明
- 提前预计算六边形的半高、行高、水平间距、奇数行水平偏移量这些固定值,避免循环内重复计算
- 外层循环每进入新行,先计算好当前行固定的Y坐标和起始X坐标,两个值不会在内层循环中被修改
- 奇偶行的交错偏移通过行起始X坐标实现,不需要在绘制列的时候反复修改Y值
- 内层循环只根据行列索引计算单个六边形的坐标,没有跨作用域的变量修改,不会产生坐标污染
修复后无论传入的size参数是奇数还是偶数,都能绘制出排列整齐的正方形六边形网格,不会出现错位问题。
内容的提问来源于stack exchange,提问作者Youcef LAIDANI
相关产品推荐
相关产品推荐

