diff --git a/src/docs/howTo/shortcuts.md b/src/docs/howTo/shortcuts.md index 2c09145..1155cee 100644 --- a/src/docs/howTo/shortcuts.md +++ b/src/docs/howTo/shortcuts.md @@ -9,6 +9,8 @@ | M | Measure Tool | | Q | Pointer Tool | | N | Note Tool | +| + | Zoom In | +| - | Zoom Out | ## Fog Tool diff --git a/src/docs/releaseNotes/v1.8.0.md b/src/docs/releaseNotes/v1.8.0.md index b0b278e..91ac30d 100644 --- a/src/docs/releaseNotes/v1.8.0.md +++ b/src/docs/releaseNotes/v1.8.0.md @@ -53,6 +53,7 @@ A GM can toggle this setting by clicking on a note once it is on the map and cli - Notes are now shown above drawings to prevent the case where you can't move your note because a drawing was on top of it. - Notes text is now left aligned and text scales down further to allow for more text to be shown per note. - Added an information dialog that is shown when joining a game that has timed out. +- Added a new zoom shortcut with the + and - keys. - Updated how to page with general site settings. - Moved shortcuts on how to page into its own section with all shortcuts listed. - Fixed a bug that would cause you join a game multiple times when using the back function in a browser. diff --git a/src/hooks/useStageInteraction.js b/src/hooks/useStageInteraction.js index 353ca40..17714ee 100644 --- a/src/hooks/useStageInteraction.js +++ b/src/hooks/useStageInteraction.js @@ -2,6 +2,8 @@ import { useRef, useEffect } from "react"; import { useGesture } from "react-use-gesture"; import normalizeWheel from "normalize-wheel"; +import { useKeyboard } from "../contexts/KeyboardContext"; + const wheelZoomSpeed = -1; const touchZoomSpeed = 0.005; const minZoom = 0.1; @@ -173,6 +175,44 @@ function useStageInteraction( }, } ); + + function handleKeyDown(event) { + // TODO: Find better way to detect whether keyboard event should fire. + // This one fires on all open stages + if (preventInteraction) { + return; + } + const { key, ctrlKey, metaKey } = event; + if ( + (key === "=" || key === "+" || key === "-" || key === "_") && + !ctrlKey && + !metaKey + ) { + const pixelY = key === "=" || key === "+" ? -100 : 100; + const newScale = Math.min( + Math.max( + stageScale + + (pixelY * wheelZoomSpeed * stageScale) / window.innerHeight, + minZoom + ), + maxZoom + ); + + // Center on pointer + const pointer = { x: window.innerWidth / 2, y: window.innerHeight / 2 }; + const newTranslate = { + x: pointer.x - ((pointer.x - stage.x()) / stageScale) * newScale, + y: pointer.y - ((pointer.y - stage.y()) / stageScale) * newScale, + }; + + stage.position(newTranslate); + stageTranslateRef.current = newTranslate; + + onStageScaleChange(newScale); + } + } + + useKeyboard(handleKeyDown); } export default useStageInteraction;