Explorar el Código

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 <luzar.david@gmail.com>
Steven Nguyen hace 5 años
padre
commit
2bfb0c20c3

+ 65 - 2
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],
+});

+ 1 - 0
src/actions/index.ts

@@ -25,6 +25,7 @@ export {
   actionZoomIn,
   actionZoomOut,
   actionResetZoom,
+  actionZoomToFit,
 } from "./actionCanvas";
 
 export { actionFinalize } from "./actionFinalize";

+ 1 - 0
src/actions/types.ts

@@ -48,6 +48,7 @@ export type ActionName =
   | "zoomIn"
   | "zoomOut"
   | "resetZoom"
+  | "zoomToFit"
   | "changeFontFamily"
   | "changeTextAlign"
   | "toggleFullScreen"

+ 4 - 0
src/components/ShortcutsDialog.tsx

@@ -229,6 +229,10 @@ export const ShortcutsDialog = ({ onClose }: { onClose?: () => void }) => {
                 shortcuts={[getShortcutKey("CtrlOrCmd+0")]}
               />
               <Shortcut
+                label={t("shortcutsDialog.zoomToFit")}
+                shortcuts={["Shift+1"]}
+              />
+              <Shortcut
                 label={t("buttons.toggleFullScreen")}
                 shortcuts={["F"]}
               />

+ 2 - 1
src/locales/en.json

@@ -150,7 +150,8 @@
     "howto": "Follow our guides",
     "github": "Found an issue? Submit",
     "textNewLine": "Add new line (text)",
-    "textFinish": "Finish editing (text)"
+    "textFinish": "Finish editing (text)",
+    "zoomToFit": "Zoom to fit all elements"
   },
   "encrypted": {
     "tooltip": "Your drawings are end-to-end encrypted so Excalidraw's servers will never see them.\nClick the icon to learn more..."