feat: Add zoom to fit for selected elements (#2522)

This commit is contained in:
Zen Tang 2020-12-13 14:54:35 -06:00 committed by GitHub
parent 59cff0f219
commit 5abe9b93e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 65 additions and 31 deletions

View File

@ -4,12 +4,14 @@ import { getDefaultAppState } from "../appState";
import { trash, zoomIn, zoomOut, resetZoom } from "../components/icons"; import { trash, zoomIn, zoomOut, resetZoom } from "../components/icons";
import { ToolButton } from "../components/ToolButton"; import { ToolButton } from "../components/ToolButton";
import { t } from "../i18n"; import { t } from "../i18n";
import { getNormalizedZoom } from "../scene"; import { getNormalizedZoom, getSelectedElements } from "../scene";
import { getNonDeletedElements } from "../element";
import { CODES, KEYS } from "../keys"; import { CODES, KEYS } from "../keys";
import { getShortcutKey } from "../utils"; import { getShortcutKey } from "../utils";
import useIsMobile from "../is-mobile"; import useIsMobile from "../is-mobile";
import { register } from "./register"; import { register } from "./register";
import { newElementWith } from "../element/mutateElement"; import { newElementWith } from "../element/mutateElement";
import { ExcalidrawElement } from "../element/types";
import { AppState, NormalizedZoomValue } from "../types"; import { AppState, NormalizedZoomValue } from "../types";
import { getCommonBounds } from "../element"; import { getCommonBounds } from "../element";
import { getNewZoom } from "../scene/zoom"; import { getNewZoom } from "../scene/zoom";
@ -204,22 +206,30 @@ const zoomValueToFitBoundsOnViewport = (
return clampedZoomValueToFitElements as NormalizedZoomValue; return clampedZoomValueToFitElements as NormalizedZoomValue;
}; };
export const actionZoomToFit = register({ const zoomToFitElements = (
name: "zoomToFit", elements: readonly ExcalidrawElement[],
perform: (elements, appState) => { appState: Readonly<AppState>,
const nonDeletedElements = elements.filter((element) => !element.isDeleted); zoomToSelection: boolean,
const commonBounds = getCommonBounds(nonDeletedElements); ) => {
const nonDeletedElements = getNonDeletedElements(elements);
const selectedElements = getSelectedElements(nonDeletedElements, appState);
const commonBounds =
zoomToSelection && selectedElements.length > 0
? getCommonBounds(selectedElements)
: getCommonBounds(nonDeletedElements);
const zoomValue = zoomValueToFitBoundsOnViewport(commonBounds, { const zoomValue = zoomValueToFitBoundsOnViewport(commonBounds, {
width: appState.width, width: appState.width,
height: appState.height, height: appState.height,
}); });
const newZoom = getNewZoom(zoomValue, appState.zoom); const newZoom = getNewZoom(zoomValue, appState.zoom);
const action = zoomToSelection ? "selection" : "fit";
const [x1, y1, x2, y2] = commonBounds; const [x1, y1, x2, y2] = commonBounds;
const centerX = (x1 + x2) / 2; const centerX = (x1 + x2) / 2;
const centerY = (y1 + y2) / 2; const centerY = (y1 + y2) / 2;
trackEvent(EVENT_ACTION, "zoom", "fit", newZoom.value * 100); trackEvent(EVENT_ACTION, "zoom", action, newZoom.value * 100);
return { return {
appState: { appState: {
...appState, ...appState,
@ -235,7 +245,21 @@ export const actionZoomToFit = register({
}, },
commitToHistory: false, commitToHistory: false,
}; };
}, };
export const actionZoomToSelected = register({
name: "zoomToSelection",
perform: (elements, appState) => zoomToFitElements(elements, appState, true),
keyTest: (event) =>
event.code === CODES.TWO &&
event.shiftKey &&
!event.altKey &&
!event[KEYS.CTRL_OR_CMD],
});
export const actionZoomToFit = register({
name: "zoomToFit",
perform: (elements, appState) => zoomToFitElements(elements, appState, false),
keyTest: (event) => keyTest: (event) =>
event.code === CODES.ONE && event.code === CODES.ONE &&
event.shiftKey && event.shiftKey &&

View File

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

View File

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

View File

@ -9,6 +9,7 @@ export const CODES = {
BRACKET_RIGHT: "BracketRight", BRACKET_RIGHT: "BracketRight",
BRACKET_LEFT: "BracketLeft", BRACKET_LEFT: "BracketLeft",
ONE: "Digit1", ONE: "Digit1",
TWO: "Digit2",
NINE: "Digit9", NINE: "Digit9",
QUOTE: "Quote", QUOTE: "Quote",
ZERO: "Digit0", ZERO: "Digit0",

View File

@ -213,6 +213,7 @@
"textNewLine": "Add new line (text)", "textNewLine": "Add new line (text)",
"textFinish": "Finish editing (text)", "textFinish": "Finish editing (text)",
"zoomToFit": "Zoom to fit all elements", "zoomToFit": "Zoom to fit all elements",
"zoomToSelection": "Zoom to selection",
"preventBinding": "Prevent arrow binding" "preventBinding": "Prevent arrow binding"
}, },
"encrypted": { "encrypted": {

View File

@ -7,11 +7,14 @@ The change should be grouped under one of the below section and must contain PR
- Chore: Changes for non src files example package.json. - Chore: Changes for non src files example package.json.
- Improvements: For any improvements. - Improvements: For any improvements.
- Refactor: For any refactoring. - Refactor: For any refactoring.
Please add the latest change on the top under the correct section.
--> -->
## [Unreleased] ## [Unreleased]
### Features ### Features
- Add zoom to selection [#2522](https://github.com/excalidraw/excalidraw/pull/2522)
- Insert Library items in the middle of the screen [#2527](https://github.com/excalidraw/excalidraw/pull/2527) - Insert Library items in the middle of the screen [#2527](https://github.com/excalidraw/excalidraw/pull/2527)
- Show shortcut context menu [#2501](https://github.com/excalidraw/excalidraw/pull/2501) - Show shortcut context menu [#2501](https://github.com/excalidraw/excalidraw/pull/2501)
- Aligns arrowhead schemas [#2517](https://github.com/excalidraw/excalidraw/pull/2517) - Aligns arrowhead schemas [#2517](https://github.com/excalidraw/excalidraw/pull/2517)