diff --git a/src/components/Grid.js b/src/components/Grid.js index 81ec0db..c1a1230 100644 --- a/src/components/Grid.js +++ b/src/components/Grid.js @@ -1,135 +1,74 @@ -import React, { useEffect, useRef } from "react"; -import { Line, Group, RegularPolygon } from "react-konva"; +import React from "react"; +import { Group, Rect } from "react-konva"; +import useImage from "use-image"; -import { getCellLocation } from "../helpers/grid"; import Vector2 from "../helpers/Vector2"; import { useGrid } from "../contexts/GridContext"; -import { useMapInteraction } from "../contexts/MapInteractionContext"; -import useDebounce from "../hooks/useDebounce"; +import squarePatternDark from "../images/SquarePatternDark.png"; +import squarePatternLight from "../images/SquarePatternLight.png"; +import hexPatternDark from "../images/HexPatternDark.png"; +import hexPatternLight from "../images/HexPatternLight.png"; -function Grid({ strokeWidth, stroke }) { - const { - grid, - gridStrokeWidth, - gridPixelSize, - gridOffset, - gridCellPixelSize, - } = useGrid(); - - const gridGroupRef = useRef(); - const { stageScale, mapWidth } = useMapInteraction(); - const debouncedStageScale = useDebounce(stageScale, 50); - useEffect(() => { - const gridGroup = gridGroupRef.current; - if (gridGroup && grid?.size.x && grid?.size.y && debouncedStageScale) { - const gridRect = gridGroup.getClientRect(); - if (gridRect.width > 0 && gridRect.height > 0) { - // 150 pixels per grid cell - const maxMapSize = Math.min( - Math.max(grid.size.x, grid.size.y) * 150, - 7680 // Max 8K - ); - const maxGridSize = - Math.max(gridRect.width, gridRect.height) / debouncedStageScale; - const maxPixelRatio = maxMapSize / maxGridSize; - gridGroup.cache({ - pixelRatio: Math.min( - Math.max(debouncedStageScale * 2, 1), - maxPixelRatio - ), - }); - } +function Grid({ stroke }) { + const { grid, gridPixelSize, gridOffset, gridCellPixelSize } = useGrid(); + let imageSource; + if (grid.type === "square") { + if (stroke === "black") { + imageSource = squarePatternDark; + } else { + imageSource = squarePatternLight; } - }, [grid, debouncedStageScale, mapWidth]); + } else { + if (stroke === "black") { + imageSource = hexPatternDark; + } else { + imageSource = hexPatternLight; + } + } + + const [patternImage] = useImage(imageSource); if (!grid?.size.x || !grid?.size.y) { return null; } const negativeGridOffset = Vector2.multiply(gridOffset, -1); - const finalStrokeWidth = gridStrokeWidth * strokeWidth; - const shapes = []; + let patternProps = {}; if (grid.type === "square") { - for (let x = 1; x < grid.size.x; x++) { - shapes.push( - - ); - } - for (let y = 1; y < grid.size.y; y++) { - shapes.push( - - ); - } - } else if (grid.type === "hexVertical" || grid.type === "hexHorizontal") { - // End at grid size + 1 to overshoot the bounds of the grid to ensure all lines are drawn - for (let x = 0; x < grid.size.x + 1; x++) { - for (let y = 0; y < grid.size.y + 1; y++) { - const cellLocation = getCellLocation(grid, x, y, gridCellPixelSize); - shapes.push( - - {/* Offset the hex tile to align to top left of grid */} - - - - - ); - } - } + // Square grid pattern is 150 DPI + const scale = gridCellPixelSize.width / 300; + patternProps.fillPatternScaleX = scale; + patternProps.fillPatternScaleY = scale; + patternProps.fillPatternOffsetX = gridCellPixelSize.width / 2; + patternProps.fillPatternOffsetY = gridCellPixelSize.height / 2; + } else if (grid.type === "hexVertical") { + // Hex tile pattern is 153 DPI to better fit hex tiles + const scale = gridCellPixelSize.width / 153; + patternProps.fillPatternScaleX = scale; + patternProps.fillPatternScaleY = scale; + patternProps.fillPatternOffsetY = gridCellPixelSize.radius / 2; + } else if (grid.type === "hexHorizontal") { + const scale = gridCellPixelSize.height / 153; + patternProps.fillPatternScaleX = scale; + patternProps.fillPatternScaleY = scale; + patternProps.fillPatternOffsetY = -gridCellPixelSize.radius / 2; + patternProps.fillPatternRotation = 90; } return ( - { - context.rect( - gridOffset.x - finalStrokeWidth / 2, - gridOffset.y - finalStrokeWidth / 2, - gridPixelSize.width + finalStrokeWidth, - gridPixelSize.height + finalStrokeWidth - ); - }} - ref={gridGroupRef} - > - {shapes} + + ); } diff --git a/src/components/map/MapEditor.js b/src/components/map/MapEditor.js index 01c553b..6ff9ef8 100644 --- a/src/components/map/MapEditor.js +++ b/src/components/map/MapEditor.js @@ -135,7 +135,7 @@ function MapEditor({ map, onSettingsChange }) { width={mapWidth} height={mapHeight} > - + )} diff --git a/src/components/map/MapGrid.js b/src/components/map/MapGrid.js index 119eb6e..1fe603b 100644 --- a/src/components/map/MapGrid.js +++ b/src/components/map/MapGrid.js @@ -8,7 +8,7 @@ import { getImageLightness } from "../../helpers/image"; import Grid from "../Grid"; -function MapGrid({ map, strokeWidth }) { +function MapGrid({ map }) { let mapSourceMap = map; // Use lowest resolution for grid lightness if (map && map.type === "file" && map.resolutions) { @@ -29,13 +29,7 @@ function MapGrid({ map, strokeWidth }) { } }, [mapImage, mapLoadingStatus]); - return ( - - ); + return ; } -MapGrid.defaultProps = { - strokeWidth: 0.1, -}; - export default MapGrid; diff --git a/src/images/HexPatternDark.png b/src/images/HexPatternDark.png new file mode 100644 index 0000000..5059cfd Binary files /dev/null and b/src/images/HexPatternDark.png differ diff --git a/src/images/HexPatternLight.png b/src/images/HexPatternLight.png new file mode 100644 index 0000000..94cf3a8 Binary files /dev/null and b/src/images/HexPatternLight.png differ diff --git a/src/images/SquarePatternDark.png b/src/images/SquarePatternDark.png new file mode 100644 index 0000000..ea64363 Binary files /dev/null and b/src/images/SquarePatternDark.png differ diff --git a/src/images/SquarePatternLight.png b/src/images/SquarePatternLight.png new file mode 100644 index 0000000..97ca1c6 Binary files /dev/null and b/src/images/SquarePatternLight.png differ