From 2bfb0c20c3d6b3b943d7c08d43c8a1da5f1ffc78 Mon Sep 17 00:00:00 2001 From: Steven Nguyen <46524488+vnsteven@users.noreply.github.com> Date: Sat, 18 Apr 2020 15:50:30 +0200 Subject: [PATCH] Add a button to show all content, if the zoom allows it. (#1406) * add zoom center action button * enhance zoom calculation and scroll to center * add zoom out and center button * filter deleted elements * improve complexity * add key shortcut * calculate zoom value * don't render zoomCenter action * offset from top to account for shape menu * change shortcut & add to shortcut dialog * decrease offset * revert offset * change hotkey & description * rename to zoomToFit * change shortcut label & position Co-authored-by: dwelle --- src/actions/actionCanvas.tsx | 67 +++++++++++++++++++++++++++++- src/actions/index.ts | 1 + src/actions/types.ts | 1 + src/components/ShortcutsDialog.tsx | 4 ++ src/locales/en.json | 3 +- 5 files changed, 73 insertions(+), 3 deletions(-) diff --git a/src/actions/actionCanvas.tsx b/src/actions/actionCanvas.tsx index 96e03c67..3f630404 100644 --- a/src/actions/actionCanvas.tsx +++ b/src/actions/actionCanvas.tsx @@ -4,13 +4,14 @@ import { getDefaultAppState } from "../appState"; import { trash, zoomIn, zoomOut, resetZoom } from "../components/icons"; import { ToolButton } from "../components/ToolButton"; import { t } from "../i18n"; -import { getNormalizedZoom } from "../scene"; +import { getNormalizedZoom, calculateScrollCenter } from "../scene"; import { KEYS } from "../keys"; import { getShortcutKey } from "../utils"; import useIsMobile from "../is-mobile"; import { register } from "./register"; import { newElementWith } from "../element/mutateElement"; -import { AppState } from "../types"; +import { AppState, FlooredNumber } from "../types"; +import { getCommonBounds } from "../element"; export const actionChangeViewBackgroundColor = register({ name: "changeViewBackgroundColor", @@ -73,6 +74,7 @@ const ZOOM_STEP = 0.1; const KEY_CODES = { MINUS: "Minus", EQUAL: "Equal", + ONE: "Digit1", ZERO: "Digit0", NUM_SUBTRACT: "NumpadSubtract", NUM_ADD: "NumpadAdd", @@ -159,3 +161,64 @@ export const actionResetZoom = register({ (event.code === KEY_CODES.ZERO || event.code === KEY_CODES.NUM_ZERO) && (event[KEYS.CTRL_OR_CMD] || event.shiftKey), }); + +const calculateZoom = ( + commonBounds: number[], + currentZoom: number, + { + scrollX, + scrollY, + }: { + scrollX: FlooredNumber; + scrollY: FlooredNumber; + }, +): number => { + const { innerWidth, innerHeight } = window; + const [x, y] = commonBounds; + const zoomX = -innerWidth / (2 * scrollX + 2 * x - innerWidth); + const zoomY = -innerHeight / (2 * scrollY + 2 * y - innerHeight); + const margin = 0.01; + let newZoom; + + if (zoomX < zoomY) { + newZoom = zoomX - margin; + } else if (zoomY <= zoomX) { + newZoom = zoomY - margin; + } else { + newZoom = currentZoom; + } + + if (newZoom <= 0.1) { + return 0.1; + } + if (newZoom >= 1) { + return 1; + } + + return newZoom; +}; + +export const actionZoomToFit = register({ + name: "zoomToFit", + perform: (elements, appState) => { + const nonDeletedElements = elements.filter((element) => !element.isDeleted); + const scrollCenter = calculateScrollCenter(nonDeletedElements); + const commonBounds = getCommonBounds(nonDeletedElements); + const zoom = calculateZoom(commonBounds, appState.zoom, scrollCenter); + + return { + appState: { + ...appState, + scrollX: scrollCenter.scrollX, + scrollY: scrollCenter.scrollY, + zoom, + }, + commitToHistory: false, + }; + }, + keyTest: (event) => + event.code === KEY_CODES.ONE && + event.shiftKey && + !event.altKey && + !event[KEYS.CTRL_OR_CMD], +}); diff --git a/src/actions/index.ts b/src/actions/index.ts index 4e186d14..885ef67e 100644 --- a/src/actions/index.ts +++ b/src/actions/index.ts @@ -25,6 +25,7 @@ export { actionZoomIn, actionZoomOut, actionResetZoom, + actionZoomToFit, } from "./actionCanvas"; export { actionFinalize } from "./actionFinalize"; diff --git a/src/actions/types.ts b/src/actions/types.ts index 85c4fc79..c3bd76bf 100644 --- a/src/actions/types.ts +++ b/src/actions/types.ts @@ -48,6 +48,7 @@ export type ActionName = | "zoomIn" | "zoomOut" | "resetZoom" + | "zoomToFit" | "changeFontFamily" | "changeTextAlign" | "toggleFullScreen" diff --git a/src/components/ShortcutsDialog.tsx b/src/components/ShortcutsDialog.tsx index 1f1504f8..94579a12 100644 --- a/src/components/ShortcutsDialog.tsx +++ b/src/components/ShortcutsDialog.tsx @@ -228,6 +228,10 @@ export const ShortcutsDialog = ({ onClose }: { onClose?: () => void }) => { label={t("buttons.resetZoom")} shortcuts={[getShortcutKey("CtrlOrCmd+0")]} /> +