diff --git a/src/components/map/MapSettings.js b/src/components/map/MapSettings.js index 367cd24..66306d7 100644 --- a/src/components/map/MapSettings.js +++ b/src/components/map/MapSettings.js @@ -4,6 +4,7 @@ import { Flex, Box, Label, Input, Checkbox, IconButton } from "theme-ui"; import ExpandMoreIcon from "../../icons/ExpandMoreIcon"; import { isEmpty } from "../../helpers/shared"; +import { getGridUpdatedInset } from "../../helpers/grid"; import Divider from "../Divider"; import Select from "../Select"; @@ -43,46 +44,34 @@ function MapSettings({ function handleGridSizeXChange(event) { const value = parseInt(event.target.value) || 0; - const gridY = map.grid.size.y; - - let inset = map.grid.inset; - - if (value > 0) { - const gridScale = - ((inset.bottomRight.x - inset.topLeft.x) * map.width) / value; - inset.bottomRight.y = inset.topLeft.y + (gridY * gridScale) / map.height; - } - - onSettingsChange("grid", { + let grid = { ...map.grid, - inset, size: { ...map.grid.size, x: value, }, - }); + }; + grid.inset = getGridUpdatedInset(grid, map.width, map.height); + onSettingsChange("grid", grid); } function handleGridSizeYChange(event) { const value = parseInt(event.target.value) || 0; - const gridX = map.grid.size.x; - - let inset = map.grid.inset; - - if (gridX > 0) { - const gridScale = - ((inset.bottomRight.x - inset.topLeft.x) * map.width) / gridX; - inset.bottomRight.y = inset.topLeft.y + (value * gridScale) / map.height; - } - - onSettingsChange("grid", { + let grid = { ...map.grid, - inset, size: { ...map.grid.size, y: value, }, - }); + }; + grid.inset = getGridUpdatedInset(grid, map.width, map.height); + onSettingsChange("grid", grid); + } + + function handleGridTypeChange(option) { + let grid = { ...map.grid, type: option.value }; + grid.inset = getGridUpdatedInset(grid, map.width, map.height); + onSettingsChange("grid", grid); } function getMapSize() { @@ -153,9 +142,7 @@ function MapSettings({ !mapEmpty && gridTypeSettings.find((s) => s.value === map.grid.type) } - onChange={(option) => - onSettingsChange("grid", { ...map.grid, type: option.value }) - } + onChange={handleGridTypeChange} isSearchable={false} /> diff --git a/src/helpers/grid.js b/src/helpers/grid.js index b290b36..772f8eb 100644 --- a/src/helpers/grid.js +++ b/src/helpers/grid.js @@ -107,7 +107,27 @@ export function shouldClampCell(grid, x, y) { } /** - * Get the default inset for a map + * Get the height of a grid based off of its width + * @param {Grid} grid + * @param {number} gridWidth + */ +function getGridHeightFromWidth(grid, gridWidth) { + switch (grid.type) { + case "square": + return (grid.size.y * gridWidth) / grid.size.x; + case "hexVertical": + const cellHeightVert = (gridWidth / grid.size.x / SQRT3) * 2; + return grid.size.y * cellHeightVert * (3 / 4) + cellHeightVert * (1 / 4); + case "hexHorizontal": + const cellHeightHroz = gridWidth / ((grid.size.x - 1) * (3 / 4) + 1); + return grid.size.y * cellHeightHroz * (SQRT3 / 2); + default: + throw GRID_TYPE_NOT_IMPLEMENTED; + } +} + +/** + * Get the default inset for a grid * @param {Grid} grid * @param {number} gridWidth * @param {number} gridHeight @@ -115,24 +135,28 @@ export function shouldClampCell(grid, x, y) { */ export function getGridDefaultInset(grid, gridWidth, gridHeight) { // Max the width of the inset and figure out the resulting height value - let y; - switch (grid.type) { - case "square": - y = grid.size.y * (gridWidth / grid.size.x); - break; - case "hexVertical": - const cellHeightVert = (gridWidth / grid.size.x / SQRT3) * 2; - y = grid.size.y * cellHeightVert * (3 / 4) + cellHeightVert * (1 / 4); - break; - case "hexHorizontal": - const cellHeightHroz = gridWidth / ((grid.size.x - 1) * (3 / 4) + 1); - y = grid.size.y * cellHeightHroz * (SQRT3 / 2); - break; - default: - throw GRID_TYPE_NOT_IMPLEMENTED; + const insetHeightNorm = getGridHeightFromWidth(grid, gridWidth) / gridHeight; + return { topLeft: { x: 0, y: 0 }, bottomRight: { x: 1, y: insetHeightNorm } }; +} + +/** + * Get an updated inset for a grid when its size changes + * @param {Grid} grid + * @param {number} mapWidth + * @param {number} mapHeight + * @returns {GridInset} + */ +export function getGridUpdatedInset(grid, mapWidth, mapHeight) { + let inset = grid.inset; + // Take current inset width and use it to calculate the new height + if (grid.size.x > 0 && grid.size.x > 0) { + // Convert to px relative to map size + const gridWidth = (inset.bottomRight.x - inset.topLeft.x) * mapWidth; + // Calculate the new inset height and convert back to normalized form + const insetHeightNorm = getGridHeightFromWidth(grid, gridWidth) / mapHeight; + inset.bottomRight.y = inset.topLeft.y + insetHeightNorm; } - const yNorm = y / gridHeight; - return { topLeft: { x: 0, y: 0 }, bottomRight: { x: 1, y: yNorm } }; + return inset; } /** diff --git a/src/modals/EditMapModal.js b/src/modals/EditMapModal.js index e44513a..466ba5b 100644 --- a/src/modals/EditMapModal.js +++ b/src/modals/EditMapModal.js @@ -66,7 +66,7 @@ function EditMapModal({ isOpen, onDone, map, mapState }) { ) { if ("size" in verifiedChanges.grid) { verifiedChanges.grid.inset = getGridDefaultInset( - verifiedChanges.grid, + { size: verifiedChanges.grid.size, type: map.grid.type }, map.width, map.height );