From 2d5589a02e8d0ab7d033f166bb650ebc7eb7f4ca Mon Sep 17 00:00:00 2001 From: Mitchell McCaffrey Date: Tue, 9 Feb 2021 16:58:14 +1100 Subject: [PATCH] Changed grid overlay to use repeating images instead of shapes --- src/components/Grid.js | 167 ++++++++++-------------------- src/components/map/MapEditor.js | 2 +- src/components/map/MapGrid.js | 10 +- src/images/HexPatternDark.png | Bin 0 -> 17919 bytes src/images/HexPatternLight.png | Bin 0 -> 17485 bytes src/images/SquarePatternDark.png | Bin 0 -> 3146 bytes src/images/SquarePatternLight.png | Bin 0 -> 3187 bytes 7 files changed, 56 insertions(+), 123 deletions(-) create mode 100644 src/images/HexPatternDark.png create mode 100644 src/images/HexPatternLight.png create mode 100644 src/images/SquarePatternDark.png create mode 100644 src/images/SquarePatternLight.png 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 0000000000000000000000000000000000000000..5059cfdb4851a4c2acf9a7a6b6847b8c4543037b GIT binary patch literal 17919 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 literal 0 HcmV?d00001 diff --git a/src/images/HexPatternLight.png b/src/images/HexPatternLight.png new file mode 100644 index 0000000000000000000000000000000000000000..94cf3a82526309726e00c7d2cfcd0b9467bb9524 GIT binary patch literal 17485 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 Rr;B4q z1>@UWv3W7q1zQ6H!|LLUdU_f@%QLx8NPKeCQ{>e5s9n-;-2`@=)JkTKVY#IfnDVn? zZg)S|)aCy7IQGOpcp35WXGN`LTzyqt-M{BsKRtc=H2?UY`H#PTt=KEKKL7Y>=|*$T zIs7xtnS`0bx76*5F8lYZ=G?ja-`yU>GBthGvy1=Z{GjLJ*Io6?)$tZ`hLv~j|cy`=A1wK_Vu^P`Sx|^_IciWHA7x#M^owV0NX7G z)P*fr&OLv=eD-zSQ-6=|zx!|5%md0y=^M_mzxuPTeBZhP*~R8e`=cLlU7O#(-XeZ` z{`2+m^)(OnAFn>R>#Cu>N&)NZs`}Q~3svoY9_GHo_FBJO>iYWg>E0XO75w>R*tq=p z^Yr^4<%~byEN8mEueQD=E*~Hf21cg(1q}&*8*lszW#QQ4|KQK(pYi?E=O^wx|8a5s*ZjJ+(myjE%8Q>k zefsqM{-5#3U*A7|`uqkxiTC$a3ff*(b)5VDy!m-MPyV7m7vf7;U;ny&AiBpm%wAsq z;I2@^{hmNS{any_bv8%s#s2i?fA$}rlmFd5&BD2K@4EcH{dJ4#1u8-w@Lc;DZgc&< z$gj&+7dP4c7uhjywz0?a*Wcd$y7Bd2)wMkP<310{Ib#m)vb%Y>#Ixdm$AO>ASG|_L z|JS(W_s8OY@&7k}oLE2o{NDpi-|K7s9}xL>nNuJGSn+(5F0x}{QBsIlXds|)K~Ev# zt@)E077iDO4Ni#)4hv!(Hr&cT@smTKqamU7kVAvR?uLY|_a}T7R1jc1$kp1&&{)QJ zFl)c!b7cnwrY2D?W=5vBOifqooX@#8IIys2i?A`V++t-}{kLsSKSLu2N0@UW7qeon%N~8`^Jq#yQ{FFw+W)8ReDrm^ggu16&UxhQ$J=>bM_g>B{Xqle%>P@< z_u2l*d1ABglj8$p)_eEv?X#;pVt)Mb?Z+SQzJC4s{(AYJpFVw>{`hPE@yE*_fBgLT z8=bDpmBG2+qoT>kDd(6dM|MwUtJ->eb{cnX2kxWfrBWv37nZh@mv$$)2 z?mX*jy+@_G3K6Dr56(XDb^G$qKOcX;^7H54-`frKIc?NGe4PDyXXa|oKUyE61Anbu z|KIARXk&oG1}BZv90E7EIj;TVo72EBDl!@xqbXrD7Yw6Zu%{XbWR6?NUqAl$>sQnB zEOq`5{xrY;w`2X@`oFIq|1JAJ?>fsop^EY~`|bsNFX+4$+!O!j(P!H)Z{HTO@7(uq zJ%9Y4r~iD{bJ{2uu)VISDX#9gYTR^f9bL)YWJkX6kJ!e~{%-Ot90EU_IXJG#Kbj>oiJ>w0LE)dTe}6x|`F_J5 zc{}$9`|H}j{`&Q6`|I|-d-nYKTJiV%F3)O2;lOhtzTC4~s#ve`lk7dSY=7N@l_G