Intento crear un lienzo con tamaño X * X, usando formas hexagonales, actualmente me baso en esta referencia , con algunas adaptaciones, mi código hasta ahora se ve así:
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>Hasta ahora, todo está bien, pero solo con tamaño impar , pero si el tamaño es par, obtengo esto:
Como principiante en JavaScript, estoy bloqueado en esto, ¿alguien tiene alguna idea de cómo puedo resolver esto, por favor?
Una cuadrícula de hexágonos tiene un espaciado regular al igual que una cuadrícula de cuadrados, sin embargo, cada segunda columna está desplazada (hacia abajo en este caso) por la mitad de la altura de los hexágonos.
Para obtener el espaciado de cuadrícula x e y, y el desplazamiento es la mitad del espaciado de cuadrícula 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;La posición del hexágono se puede calcular usando (gx, gy son posiciones de columna y fila)
function gridToPixel(gx, gy, p = {}) { px = gx * GRID_X_SPACE; py = gy * GRID_Y_SPACE + (gx % 2 ? GRID_Y_OFFSET : 0); return p; }El ejemplo llena el lienzo con una cuadrícula hexagonal.
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; const COLS = "=#3c2f18,#01335f,#3f0e77,#204a73,#511d94,#fe1f00,#0060fd,#fe7603,#f0ca1d,#b085e8,#e9cafa".split(","); const rndItem = arr => arr[Math.random() * arr.length | 0]; drawGrid(1, 1, 15, 13, createPoly(EDGES)); function drawGrid(x, y, w, h, points) { const p = P2(); var gy, gx; for (gy = y; gy < y + h; gy++) { for (gx = x; gx < x + w; gx++) { ctx.fillStyle = rndItem(COLS); drawPoly(gridToPixel(gx, gy, p), points); } } } function gridToPixel(gx, gy, p = {}) { px = gx * GRID_X_SPACE; py = gy * GRID_Y_SPACE + (gx % 2 ? GRID_Y_OFFSET : 0); return p; } function drawPoly(p, points) { // px, py is center ctx.setTransform(1, 0, 0, 1, px, py); var i = 0; ctx.beginPath(); while (i < points.length) { const p2 = points[i++]; ctx.lineTo(p2.x, p2.y); } ctx.closePath(); ctx.fill(); ctx.stroke(); } 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>