Browse Source

fix: stop flooring scroll positions (#2883)

David Luzar 4 years ago
parent
commit
1973ae9444

+ 3 - 3
src/appState.ts

@@ -5,7 +5,7 @@ import {
   DEFAULT_TEXT_ALIGN,
 } from "./constants";
 import { t } from "./i18n";
-import { AppState, FlooredNumber, NormalizedZoomValue } from "./types";
+import { AppState, NormalizedZoomValue } from "./types";
 import { getDateTime } from "./utils";
 
 export const getDefaultAppState = (): Omit<
@@ -56,8 +56,8 @@ export const getDefaultAppState = (): Omit<
     previousSelectedElementIds: {},
     resizingElement: null,
     scrolledOutside: false,
-    scrollX: 0 as FlooredNumber,
-    scrollY: 0 as FlooredNumber,
+    scrollX: 0,
+    scrollY: 0,
     selectedElementIds: {},
     selectedGroupIds: {},
     selectionElement: null,

+ 9 - 18
src/components/App.tsx

@@ -147,7 +147,6 @@ import {
   getSelectedElements,
   isOverScrollBars,
   isSomeElementSelected,
-  normalizeScroll,
 } from "../scene";
 import Scene from "../scene/Scene";
 import { SceneState, ScrollBars } from "../scene/types";
@@ -1745,8 +1744,8 @@ class App extends React.Component<ExcalidrawProps, AppState> {
       const scaleFactor = distance / gesture.initialDistance;
 
       this.setState(({ zoom, scrollX, scrollY, offsetLeft, offsetTop }) => ({
-        scrollX: normalizeScroll(scrollX + deltaX / zoom.value),
-        scrollY: normalizeScroll(scrollY + deltaY / zoom.value),
+        scrollX: scrollX + deltaX / zoom.value,
+        scrollY: scrollY + deltaY / zoom.value,
         zoom: getNewZoom(
           getNormalizedZoom(initialScale * scaleFactor),
           zoom,
@@ -2157,12 +2156,8 @@ class App extends React.Component<ExcalidrawProps, AppState> {
       }
 
       this.setState({
-        scrollX: normalizeScroll(
-          this.state.scrollX - deltaX / this.state.zoom.value,
-        ),
-        scrollY: normalizeScroll(
-          this.state.scrollY - deltaY / this.state.zoom.value,
-        ),
+        scrollX: this.state.scrollX - deltaX / this.state.zoom.value,
+        scrollY: this.state.scrollY - deltaY / this.state.zoom.value,
       });
     });
     const teardown = withBatchedUpdates(
@@ -2976,9 +2971,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
       const x = event.clientX;
       const dx = x - pointerDownState.lastCoords.x;
       this.setState({
-        scrollX: normalizeScroll(
-          this.state.scrollX - dx / this.state.zoom.value,
-        ),
+        scrollX: this.state.scrollX - dx / this.state.zoom.value,
       });
       pointerDownState.lastCoords.x = x;
       return true;
@@ -2988,9 +2981,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
       const y = event.clientY;
       const dy = y - pointerDownState.lastCoords.y;
       this.setState({
-        scrollY: normalizeScroll(
-          this.state.scrollY - dy / this.state.zoom.value,
-        ),
+        scrollY: this.state.scrollY - dy / this.state.zoom.value,
       });
       pointerDownState.lastCoords.y = y;
       return true;
@@ -3741,14 +3732,14 @@ class App extends React.Component<ExcalidrawProps, AppState> {
     if (event.shiftKey) {
       this.setState(({ zoom, scrollX }) => ({
         // on Mac, shift+wheel tends to result in deltaX
-        scrollX: normalizeScroll(scrollX - (deltaY || deltaX) / zoom.value),
+        scrollX: scrollX - (deltaY || deltaX) / zoom.value,
       }));
       return;
     }
 
     this.setState(({ zoom, scrollX, scrollY }) => ({
-      scrollX: normalizeScroll(scrollX - deltaX / zoom.value),
-      scrollY: normalizeScroll(scrollY - deltaY / zoom.value),
+      scrollX: scrollX - deltaX / zoom.value,
+      scrollY: scrollY - deltaY / zoom.value,
     }));
   });
 

+ 2 - 3
src/gesture.ts

@@ -1,11 +1,10 @@
 import { PointerCoords } from "./types";
-import { normalizeScroll } from "./scene";
 
 export const getCenter = (pointers: Map<number, PointerCoords>) => {
   const allCoords = Array.from(pointers.values());
   return {
-    x: normalizeScroll(sum(allCoords, (coords) => coords.x) / allCoords.length),
-    y: normalizeScroll(sum(allCoords, (coords) => coords.y) / allCoords.length),
+    x: sum(allCoords, (coords) => coords.x) / allCoords.length,
+    y: sum(allCoords, (coords) => coords.y) / allCoords.length,
   };
 };
 

+ 2 - 3
src/scene/export.ts

@@ -5,7 +5,6 @@ import { NonDeletedExcalidrawElement } from "../element/types";
 import { getCommonBounds } from "../element/bounds";
 import { renderScene, renderSceneToSvg } from "../renderer/renderScene";
 import { distance, SVG_NS } from "../utils";
-import { normalizeScroll } from "./scroll";
 import { AppState } from "../types";
 import { t } from "../i18n";
 import { DEFAULT_FONT_FAMILY, DEFAULT_VERTICAL_ALIGN } from "../constants";
@@ -59,8 +58,8 @@ export const exportToCanvas = (
     tempCanvas,
     {
       viewBackgroundColor: exportBackground ? viewBackgroundColor : null,
-      scrollX: normalizeScroll(-minX + exportPadding),
-      scrollY: normalizeScroll(-minY + exportPadding),
+      scrollX: -minX + exportPadding,
+      scrollY: -minY + exportPadding,
       zoom: getDefaultAppState().zoom,
       remotePointerViewportCoords: {},
       remoteSelectedElementIds: {},

+ 1 - 1
src/scene/index.ts

@@ -6,7 +6,7 @@ export {
   getSelectedElements,
   getTargetElements,
 } from "./selection";
-export { normalizeScroll, calculateScrollCenter } from "./scroll";
+export { calculateScrollCenter } from "./scroll";
 export {
   hasBackground,
   hasStroke,

+ 10 - 15
src/scene/scroll.ts

@@ -1,4 +1,4 @@
-import { AppState, FlooredNumber, PointerCoords, Zoom } from "../types";
+import { AppState, PointerCoords, Zoom } from "../types";
 import { ExcalidrawElement } from "../element/types";
 import { getCommonBounds, getClosestElementBounds } from "../element";
 
@@ -7,9 +7,6 @@ import {
   viewportCoordsToSceneCoords,
 } from "../utils";
 
-export const normalizeScroll = (pos: number) =>
-  Math.floor(pos) as FlooredNumber;
-
 const isOutsideViewPort = (
   appState: AppState,
   canvas: HTMLCanvasElement | null,
@@ -40,16 +37,14 @@ export const centerScrollOn = ({
   zoom: Zoom;
 }) => {
   return {
-    scrollX: normalizeScroll(
+    scrollX:
       (viewportDimensions.width / 2) * (1 / zoom.value) -
-        scenePoint.x -
-        zoom.translation.x * (1 / zoom.value),
-    ),
-    scrollY: normalizeScroll(
+      scenePoint.x -
+      zoom.translation.x * (1 / zoom.value),
+    scrollY:
       (viewportDimensions.height / 2) * (1 / zoom.value) -
-        scenePoint.y -
-        zoom.translation.y * (1 / zoom.value),
-    ),
+      scenePoint.y -
+      zoom.translation.y * (1 / zoom.value),
   };
 };
 
@@ -57,11 +52,11 @@ export const calculateScrollCenter = (
   elements: readonly ExcalidrawElement[],
   appState: AppState,
   canvas: HTMLCanvasElement | null,
-): { scrollX: FlooredNumber; scrollY: FlooredNumber } => {
+): { scrollX: number; scrollY: number } => {
   if (!elements.length) {
     return {
-      scrollX: normalizeScroll(0),
-      scrollY: normalizeScroll(0),
+      scrollX: 0,
+      scrollY: 0,
     };
   }
   let [x1, y1, x2, y2] = getCommonBounds(elements);

+ 3 - 3
src/scene/scrollbars.ts

@@ -1,6 +1,6 @@
 import { ExcalidrawElement } from "../element/types";
 import { getCommonBounds } from "../element";
-import { FlooredNumber, Zoom } from "../types";
+import { Zoom } from "../types";
 import { ScrollBars } from "./types";
 import { getGlobalCSSVariable } from "../utils";
 import { getLanguage } from "../i18n";
@@ -18,8 +18,8 @@ export const getScrollBars = (
     scrollY,
     zoom,
   }: {
-    scrollX: FlooredNumber;
-    scrollY: FlooredNumber;
+    scrollX: number;
+    scrollY: number;
     zoom: Zoom;
   },
 ): ScrollBars => {

+ 5 - 5
src/scene/types.ts

@@ -1,9 +1,9 @@
 import { ExcalidrawTextElement } from "../element/types";
-import { FlooredNumber, Zoom } from "../types";
+import { Zoom } from "../types";
 
 export type SceneState = {
-  scrollX: FlooredNumber;
-  scrollY: FlooredNumber;
+  scrollX: number;
+  scrollY: number;
   // null indicates transparent bg
   viewBackgroundColor: string | null;
   zoom: Zoom;
@@ -15,8 +15,8 @@ export type SceneState = {
 };
 
 export type SceneScroll = {
-  scrollX: FlooredNumber;
-  scrollY: FlooredNumber;
+  scrollX: number;
+  scrollY: number;
 };
 
 export interface Scene {

+ 4 - 4
src/tests/__snapshots__/regressionTests.test.tsx.snap

@@ -12705,7 +12705,7 @@ Object {
   },
   "previousSelectedElementIds": Object {},
   "resizingElement": null,
-  "scrollX": -6,
+  "scrollX": -5.416666666666667,
   "scrollY": 0,
   "scrolledOutside": false,
   "selectedElementIds": Object {
@@ -12725,7 +12725,7 @@ Object {
   "zenModeEnabled": false,
   "zoom": Object {
     "translation": Object {
-      "x": 0.3333333333333357,
+      "x": 0.4166666666666714,
       "y": 0,
     },
     "value": 1,
@@ -20330,7 +20330,7 @@ Object {
   },
   "previousSelectedElementIds": Object {},
   "resizingElement": null,
-  "scrollX": 11,
+  "scrollX": 11.046099290780141,
   "scrollY": -5,
   "scrolledOutside": false,
   "selectedElementIds": Object {
@@ -20350,7 +20350,7 @@ Object {
   "zenModeEnabled": false,
   "zoom": Object {
     "translation": Object {
-      "x": -60.420000000000016,
+      "x": -59.425,
       "y": -48.66347517730496,
     },
     "value": 1.99,

+ 2 - 3
src/types.ts

@@ -21,7 +21,6 @@ import type { ResolvablePromise } from "./utils";
 import { Spreadsheet } from "./charts";
 import { Language } from "./i18n";
 
-export type FlooredNumber = number & { _brand: "FlooredNumber" };
 export type Point = Readonly<RoughPoint>;
 
 export type Collaborator = {
@@ -68,8 +67,8 @@ export type AppState = {
   currentItemEndArrowhead: Arrowhead | null;
   currentItemLinearStrokeSharpness: ExcalidrawElement["strokeSharpness"];
   viewBackgroundColor: string;
-  scrollX: FlooredNumber;
-  scrollY: FlooredNumber;
+  scrollX: number;
+  scrollY: number;
   cursorButton: "up" | "down";
   scrolledOutside: boolean;
   name: string;