Repository: excalidraw/excalidraw
File: packages/excalidraw/components/App.tsx (TypeScript)

Code before:
      const scaleFactor =
        this.state.activeTool.type === "freedraw" && this.state.penMode
          ? 1
          : distance / gesture.initialDistance;

      const nextZoom = scaleFactor
        ? getNormalizedZoom(initialScale * scaleFactor)
        : this.state.zoom.value;

      this.setState((state) => {
        const zoomState = getStateForZoom(
          {
            viewportX: center.x,
            viewportY: center.y,
            nextZoom,
          },
          state,
        );

        this.translateCanvas({
          zoom: zoomState.zoom,
          scrollX: zoomState.scrollX + 2 * (deltaX / nextZoom),
          scrollY: zoomState.scrollY + 2 * (deltaY / nextZoom),
          shouldCacheIgnoreZoom: true,
        });
      });
      this.resetShouldCacheIgnoreZoomDebounced();
    } else {
      gesture.lastCenter =
        gesture.initialDistance =
        gesture.initialScale =
          null;
    }

    if (
      isHoldingSpace ||
      isPanning ||
      isDraggingScrollBar ||
      isHandToolActive(this.state)
    ) {
      return;
    }

    const isPointerOverScrollBars = isOverScrollBars(
      currentScrollBars,
      event.clientX - this.state.offsetLeft,
      event.clientY - this.state.offsetTop,
    );
    const isOverScrollBar = isPointerOverScrollBars.isOverEither;
    if (!this.state.draggingElement && !this.state.multiElement) {
      if (isOverScrollBar) {

Review comment (performance):
```suggestion
          // 2x multiplier is just a magic number that makes this work correctly
          // on touchscreen devices (note: if we get report that panning is slower/faster
          // than actual movement, consider swapping with devicePixelRatio)
          scrollX: zoomState.scrollX + 2 * (deltaX / nextZoom),
          scrollY: zoomState.scrollY + 2 * (deltaY / nextZoom),
```

Code after:
      const scaleFactor =
        this.state.activeTool.type === "freedraw" && this.state.penMode
          ? 1
          : distance / gesture.initialDistance;

      const nextZoom = scaleFactor
        ? getNormalizedZoom(initialScale * scaleFactor)
        : this.state.zoom.value;

      this.setState((state) => {
        const zoomState = getStateForZoom(
          {
            viewportX: center.x,
            viewportY: center.y,
            nextZoom,
          },
          state,
        );

        this.translateCanvas({
          zoom: zoomState.zoom,
          // 2x multiplier is just a magic number that makes this work correctly
          // on touchscreen devices (note: if we get report that panning is slower/faster
          // than actual movement, consider swapping with devicePixelRatio)
          scrollX: zoomState.scrollX + 2 * (deltaX / nextZoom),
          scrollY: zoomState.scrollY + 2 * (deltaY / nextZoom),
          shouldCacheIgnoreZoom: true,
        });
      });
      this.resetShouldCacheIgnoreZoomDebounced();
    } else {
      gesture.lastCenter =
        gesture.initialDistance =
        gesture.initialScale =
          null;
    }

    if (
      isHoldingSpace ||
      isPanning ||
      isDraggingScrollBar ||
      isHandToolActive(this.state)
    ) {
      return;
    }

    const isPointerOverScrollBars = isOverScrollBars(
      currentScrollBars,
      event.clientX - this.state.offsetLeft,
      event.clientY - this.state.offsetTop,
    );