Ver código fonte

fix: Visibility and zooming when canvas offset is not zero (#2534)

João Forja 4 anos atrás
pai
commit
4c7b1a2269

+ 15 - 5
src/actions/actionCanvas.tsx

@@ -95,6 +95,7 @@ export const actionZoomIn = register({
     const zoom = getNewZoom(
       getNormalizedZoom(appState.zoom.value + ZOOM_STEP),
       appState.zoom,
+      { left: appState.offsetLeft, top: appState.offsetTop },
       { x: appState.width / 2, y: appState.height / 2 },
     );
     trackEvent(EVENT_ACTION, "zoom", "in", zoom.value * 100);
@@ -128,6 +129,7 @@ export const actionZoomOut = register({
     const zoom = getNewZoom(
       getNormalizedZoom(appState.zoom.value - ZOOM_STEP),
       appState.zoom,
+      { left: appState.offsetLeft, top: appState.offsetTop },
       { x: appState.width / 2, y: appState.height / 2 },
     );
 
@@ -163,10 +165,15 @@ export const actionResetZoom = register({
     return {
       appState: {
         ...appState,
-        zoom: getNewZoom(1 as NormalizedZoomValue, appState.zoom, {
-          x: appState.width / 2,
-          y: appState.height / 2,
-        }),
+        zoom: getNewZoom(
+          1 as NormalizedZoomValue,
+          appState.zoom,
+          { left: appState.offsetLeft, top: appState.offsetTop },
+          {
+            x: appState.width / 2,
+            y: appState.height / 2,
+          },
+        ),
       },
       commitToHistory: false,
     };
@@ -223,7 +230,10 @@ const zoomToFitElements = (
     width: appState.width,
     height: appState.height,
   });
-  const newZoom = getNewZoom(zoomValue, appState.zoom);
+  const newZoom = getNewZoom(zoomValue, appState.zoom, {
+    left: appState.offsetLeft,
+    top: appState.offsetTop,
+  });
   const action = zoomToSelection ? "selection" : "fit";
 
   const [x1, y1, x2, y2] = commonBounds;

+ 17 - 10
src/components/App.tsx

@@ -1423,10 +1423,11 @@ class App extends React.Component<ExcalidrawProps, AppState> {
 
   private onGestureChange = withBatchedUpdates((event: GestureEvent) => {
     event.preventDefault();
-    this.setState(({ zoom }) => ({
+    this.setState(({ zoom, offsetLeft, offsetTop }) => ({
       zoom: getNewZoom(
         getNormalizedZoom(gesture.initialScale! * event.scale),
         zoom,
+        { left: offsetLeft, top: offsetTop },
         { x: cursorX, y: cursorY },
       ),
     }));
@@ -1750,12 +1751,13 @@ class App extends React.Component<ExcalidrawProps, AppState> {
       const distance = getDistance(Array.from(gesture.pointers.values()));
       const scaleFactor = distance / gesture.initialDistance!;
 
-      this.setState(({ zoom, scrollX, scrollY }) => ({
+      this.setState(({ zoom, scrollX, scrollY, offsetLeft, offsetTop }) => ({
         scrollX: normalizeScroll(scrollX + deltaX / zoom.value),
         scrollY: normalizeScroll(scrollY + deltaY / zoom.value),
         zoom: getNewZoom(
           getNormalizedZoom(gesture.initialScale! * scaleFactor),
           zoom,
+          { left: offsetLeft, top: offsetTop },
           center,
         ),
         shouldCacheIgnoreZoom: true,
@@ -2586,9 +2588,9 @@ class App extends React.Component<ExcalidrawProps, AppState> {
       );
 
       /* If arrow is pre-arrowheads, it will have undefined for both start and end arrowheads.
-			 If so, we want it to be null for start and "arrow" for end. If the linear item is not 
-			 an arrow, we want it to be null for both. Otherwise, we want it to use the 
-			 values from appState. */
+      If so, we want it to be null for start and "arrow" for end. If the linear item is not
+      an arrow, we want it to be null for both. Otherwise, we want it to use the
+      values from appState. */
 
       const { currentItemStartArrowhead, currentItemEndArrowhead } = this.state;
       const [startArrowhead, endArrowhead] =
@@ -3702,11 +3704,16 @@ class App extends React.Component<ExcalidrawProps, AppState> {
         }, 1000);
       }
 
-      this.setState(({ zoom }) => ({
-        zoom: getNewZoom(getNormalizedZoom(zoom.value - delta / 100), zoom, {
-          x: cursorX,
-          y: cursorY,
-        }),
+      this.setState(({ zoom, offsetLeft, offsetTop }) => ({
+        zoom: getNewZoom(
+          getNormalizedZoom(zoom.value - delta / 100),
+          zoom,
+          { left: offsetLeft, top: offsetTop },
+          {
+            x: cursorX,
+            y: cursorY,
+          },
+        ),
         selectedElementIds: {},
         previousSelectedElementIds:
           Object.keys(selectedElementIds).length !== 0

+ 7 - 0
src/packages/excalidraw/CHANGELOG.MD

@@ -1,4 +1,5 @@
 # Changelog
+
 <!--
 Guidelines for changelog:
 The change should be grouped under one of the below section and must contain PR link.
@@ -14,6 +15,7 @@ Please add the latest change on the top under the correct section.
 ## [Unreleased]
 
 ### 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)
 - Show shortcut context menu [#2501](https://github.com/excalidraw/excalidraw/pull/2501)
@@ -23,9 +25,12 @@ Please add the latest change on the top under the correct section.
 - Support CSV graphs and improve the look and feel [#2495](https://github.com/excalidraw/excalidraw/pull/2495)
 
 ### Fixes
+
+- Fix element visibility and zoom on cursor when canvas offset isn't 0. [#2534](https://github.com/excalidraw/excalidraw/pull/2534)
 - Fix Library Menu Layout [#2502](https://github.com/excalidraw/excalidraw/pull/2502)
 
 ### Improvements
+
 - Add tooltip with icon for embedding scenes [#2532](https://github.com/excalidraw/excalidraw/pull/2532)
 - RTL support for the stats dialog [#2530](https://github.com/excalidraw/excalidraw/pull/2530)
 - Expand canvas padding based on zoom. [#2515](https://github.com/excalidraw/excalidraw/pull/2515)
@@ -33,11 +38,13 @@ Please add the latest change on the top under the correct section.
 - Hide stats and scrollToContent-button when mobile menus open [#2509](https://github.com/excalidraw/excalidraw/pull/2509)
 
 ### Chore
+
 - Bump ini from 1.3.5 to 1.3.7 in /src/packages/excalidraw [#2500](https://github.com/excalidraw/excalidraw/pull/2500)
 
 ## 0.1.1
 
 #### Fix
+
 - Update the homepage URL so it redirects to correct readme [#2498](https://github.com/excalidraw/excalidraw/pull/2498)
 
 ## 0.1.0

+ 9 - 2
src/renderer/renderScene.ts

@@ -763,13 +763,20 @@ const isVisibleElement = (
 ) => {
   const [x1, y1, x2, y2] = getElementBounds(element); // scene coordinates
   const topLeftSceneCoords = viewportCoordsToSceneCoords(
-    { clientX: 0, clientY: 0 },
+    {
+      clientX: viewTransformations.offsetLeft,
+      clientY: viewTransformations.offsetTop,
+    },
     viewTransformations,
   );
   const bottomRightSceneCoords = viewportCoordsToSceneCoords(
-    { clientX: canvasWidth, clientY: canvasHeight },
+    {
+      clientX: viewTransformations.offsetLeft + canvasWidth,
+      clientY: viewTransformations.offsetTop + canvasHeight,
+    },
     viewTransformations,
   );
+
   return (
     topLeftSceneCoords.x <= x2 &&
     topLeftSceneCoords.y <= y2 &&

+ 5 - 2
src/scene/zoom.ts

@@ -3,6 +3,7 @@ import { NormalizedZoomValue, PointerCoords, Zoom } from "../types";
 export const getNewZoom = (
   newZoomValue: NormalizedZoomValue,
   prevZoom: Zoom,
+  canvasOffset: { left: number; top: number },
   zoomOnViewportPoint: PointerCoords = { x: 0, y: 0 },
 ): Zoom => {
   return {
@@ -10,11 +11,13 @@ export const getNewZoom = (
     translation: {
       x:
         zoomOnViewportPoint.x -
-        (zoomOnViewportPoint.x - prevZoom.translation.x) *
+        canvasOffset.left -
+        (zoomOnViewportPoint.x - canvasOffset.left - prevZoom.translation.x) *
           (newZoomValue / prevZoom.value),
       y:
         zoomOnViewportPoint.y -
-        (zoomOnViewportPoint.y - prevZoom.translation.y) *
+        canvasOffset.top -
+        (zoomOnViewportPoint.y - canvasOffset.top - prevZoom.translation.y) *
           (newZoomValue / prevZoom.value),
     },
   };