diff --git a/src/components/Grid.js b/src/components/Grid.js index 40a5b91..9dda566 100644 --- a/src/components/Grid.js +++ b/src/components/Grid.js @@ -2,7 +2,12 @@ import React from "react"; import { Line, Group, RegularPolygon } from "react-konva"; import { getStrokeWidth } from "../helpers/drawing"; -import { getCellSize, getCellLocation, shouldClampCell } from "../helpers/grid"; +import { + getCellSize, + getCellLocation, + gridClipFunction, + shouldClipCell, +} from "../helpers/grid"; function Grid({ grid, strokeWidth, width, height, stroke }) { if (!grid?.size.x || !grid?.size.y) { @@ -62,30 +67,16 @@ function Grid({ grid, strokeWidth, width, height, stroke }) { ); } } else if (grid.type === "hexVertical" || grid.type === "hexHorizontal") { - for (let x = 0; x < grid.size.x; x++) { - for (let y = 0; y < grid.size.y; y++) { + // Start at -1 to overshoot the bounds of the grid to ensure all lines are drawn + for (let x = -1; x < grid.size.x; x++) { + for (let y = -1; y < grid.size.y; y++) { const cellLocation = getCellLocation(grid, x, y, cellSize); - - // If our hex shape will go past the bounds of the grid - const overshot = shouldClampCell(grid, x, y); shapes.push( { - context.rect( - -cellSize.radius, - -cellSize.radius, - grid.type === "hexVertical" - ? cellSize.radius - : cellSize.radius * 2, - grid.type === "hexVertical" - ? cellSize.radius * 2 - : cellSize.radius - ); - }) + shouldClipCell(grid, x, y) && + ((context) => gridClipFunction(context, grid, x, y, cellSize)) } x={cellLocation.x} y={cellLocation.y} diff --git a/src/helpers/grid.js b/src/helpers/grid.js index 772f8eb..554e2cc 100644 --- a/src/helpers/grid.js +++ b/src/helpers/grid.js @@ -93,7 +93,10 @@ export function getCellLocation(grid, x, y, cellSize) { * @param {number} y Y-axis location of the cell * @returns {boolean} */ -export function shouldClampCell(grid, x, y) { +export function shouldClipCell(grid, x, y) { + if (x < 0 || y < 0) { + return true; + } switch (grid.type) { case "square": return false; @@ -106,6 +109,32 @@ export function shouldClampCell(grid, x, y) { } } +/** + * Canvas clip function for culling hex cells that overshoot/undershoot the grid + * @param {CanvasRenderingContext2D} context + * @param {Grid} grid + * @param {number} x + * @param {number} y + * @param {CellSize} cellSize + */ +export function gridClipFunction(context, grid, x, y, cellSize) { + // Clip the undershooting cells unless they are needed to fill out a specific grid type + if ((x < 0 && grid.type !== "hexVertical") || (x < 0 && y % 2 === 0)) { + return; + } + if ((y < 0 && grid.type !== "hexHorizontal") || (y < 0 && x % 2 === 0)) { + return; + } + context.rect( + x < 0 ? 0 : -cellSize.radius, + y < 0 ? 0 : -cellSize.radius, + x > 0 && grid.type === "hexVertical" + ? cellSize.radius + : cellSize.radius * 2, + y > 0 && grid.type === "hexVertical" ? cellSize.radius * 2 : cellSize.radius + ); +} + /** * Get the height of a grid based off of its width * @param {Grid} grid