refactor: simplify zoom by removing zoom.translation (#4477)

This commit is contained in:
David Luzar 2022-01-29 21:12:44 +01:00 committed by GitHub
parent e4edda4555
commit 79d323fab1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 152 additions and 408 deletions

View File

@ -9,7 +9,7 @@ import { t } from "../i18n";
import { CODES, KEYS } from "../keys";
import { getNormalizedZoom, getSelectedElements } from "../scene";
import { centerScrollOn } from "../scene/scroll";
import { getNewZoom } from "../scene/zoom";
import { getStateForZoom } from "../scene/zoom";
import { AppState, NormalizedZoomValue } from "../types";
import { getShortcutKey } from "../utils";
import { register } from "./register";
@ -73,17 +73,18 @@ export const actionClearCanvas = register({
export const actionZoomIn = register({
name: "zoomIn",
perform: (_elements, appState) => {
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 },
);
perform: (_elements, appState, _, app) => {
return {
appState: {
...appState,
zoom,
...getStateForZoom(
{
viewportX: appState.width / 2 + appState.offsetLeft,
viewportY: appState.height / 2 + appState.offsetTop,
nextZoom: getNormalizedZoom(appState.zoom.value + ZOOM_STEP),
},
appState,
),
},
commitToHistory: false,
};
@ -107,18 +108,18 @@ export const actionZoomIn = register({
export const actionZoomOut = register({
name: "zoomOut",
perform: (_elements, appState) => {
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 },
);
perform: (_elements, appState, _, app) => {
return {
appState: {
...appState,
zoom,
...getStateForZoom(
{
viewportX: appState.width / 2 + appState.offsetLeft,
viewportY: appState.height / 2 + appState.offsetTop,
nextZoom: getNormalizedZoom(appState.zoom.value - ZOOM_STEP),
},
appState,
),
},
commitToHistory: false,
};
@ -142,18 +143,17 @@ export const actionZoomOut = register({
export const actionResetZoom = register({
name: "resetZoom",
perform: (_elements, appState) => {
perform: (_elements, appState, _, app) => {
return {
appState: {
...appState,
zoom: getNewZoom(
1 as NormalizedZoomValue,
appState.zoom,
{ left: appState.offsetLeft, top: appState.offsetTop },
...getStateForZoom(
{
x: appState.width / 2,
y: appState.height / 2,
viewportX: appState.width / 2 + appState.offsetLeft,
viewportY: appState.height / 2 + appState.offsetTop,
nextZoom: getNormalizedZoom(1),
},
appState,
),
},
commitToHistory: false,
@ -212,14 +212,12 @@ const zoomToFitElements = (
? getCommonBounds(selectedElements)
: getCommonBounds(nonDeletedElements);
const zoomValue = zoomValueToFitBoundsOnViewport(commonBounds, {
width: appState.width,
height: appState.height,
});
const newZoom = getNewZoom(zoomValue, appState.zoom, {
left: appState.offsetLeft,
top: appState.offsetTop,
});
const newZoom = {
value: zoomValueToFitBoundsOnViewport(commonBounds, {
width: appState.width,
height: appState.height,
}),
};
const [x1, y1, x2, y2] = commonBounds;
const centerX = (x1 + x2) / 2;

View File

@ -77,7 +77,9 @@ export const getDefaultAppState = (): Omit<
toastMessage: null,
viewBackgroundColor: oc.white,
zenModeEnabled: false,
zoom: { value: 1 as NormalizedZoomValue, translation: { x: 0, y: 0 } },
zoom: {
value: 1 as NormalizedZoomValue,
},
viewModeEnabled: false,
pendingImageElement: null,
};

View File

@ -177,7 +177,7 @@ import {
} from "../scene";
import Scene from "../scene/Scene";
import { RenderConfig, ScrollBars } from "../scene/types";
import { getNewZoom } from "../scene/zoom";
import { getStateForZoom } from "../scene/zoom";
import { findShapeByKey } from "../shapes";
import {
AppClassProperties,
@ -1880,12 +1880,14 @@ class App extends React.Component<AppProps, AppState> {
const initialScale = gesture.initialScale;
if (initialScale) {
this.setState(({ zoom, offsetLeft, offsetTop }) => ({
zoom: getNewZoom(
getNormalizedZoom(initialScale * event.scale),
zoom,
{ left: offsetLeft, top: offsetTop },
{ x: cursorX, y: cursorY },
this.setState((state) => ({
...getStateForZoom(
{
viewportX: cursorX,
viewportY: cursorY,
nextZoom: getNormalizedZoom(initialScale * event.scale),
},
state,
),
}));
}
@ -2323,17 +2325,27 @@ class App extends React.Component<AppProps, AppState> {
const distance = getDistance(Array.from(gesture.pointers.values()));
const scaleFactor = distance / gesture.initialDistance;
this.setState(({ zoom, scrollX, scrollY, offsetLeft, offsetTop }) => ({
scrollX: scrollX + deltaX / zoom.value,
scrollY: scrollY + deltaY / zoom.value,
zoom: getNewZoom(
getNormalizedZoom(initialScale * scaleFactor),
zoom,
{ left: offsetLeft, top: offsetTop },
center,
),
shouldCacheIgnoreZoom: true,
}));
const nextZoom = scaleFactor
? getNormalizedZoom(initialScale * scaleFactor)
: this.state.zoom.value;
this.setState((state) => {
const zoomState = getStateForZoom(
{
viewportX: center.x,
viewportY: center.y,
nextZoom,
},
state,
);
return {
zoom: zoomState.zoom,
scrollX: zoomState.scrollX + deltaX / nextZoom,
scrollY: zoomState.scrollY + deltaY / nextZoom,
shouldCacheIgnoreZoom: true,
};
});
this.resetShouldCacheIgnoreZoomDebounced();
} else {
gesture.lastCenter =
@ -2824,6 +2836,7 @@ class App extends React.Component<AppProps, AppState> {
x: event.clientX,
y: event.clientY,
});
// console.log("PointerDown", event.pointerId, "size:", gesture.pointers.size);
if (gesture.pointers.size === 2) {
gesture.lastCenter = getCenter(gesture.pointers);
@ -2831,6 +2844,7 @@ class App extends React.Component<AppProps, AppState> {
gesture.initialDistance = getDistance(
Array.from(gesture.pointers.values()),
);
// console.log("gesture >>>>", gesture);
}
}
@ -5111,15 +5125,14 @@ class App extends React.Component<AppProps, AppState> {
// round to nearest step
newZoom = Math.round(newZoom * ZOOM_STEP * 100) / (ZOOM_STEP * 100);
this.setState(({ zoom, offsetLeft, offsetTop }) => ({
zoom: getNewZoom(
getNormalizedZoom(newZoom),
zoom,
{ left: offsetLeft, top: offsetTop },
this.setState((state) => ({
...getStateForZoom(
{
x: cursorX,
y: cursorY,
viewportX: cursorX,
viewportY: cursorY,
nextZoom: getNormalizedZoom(newZoom),
},
state,
),
selectedElementIds: {},
previousSelectedElementIds:

View File

@ -261,7 +261,6 @@ export const restoreAppState = (
typeof appState.zoom === "number"
? {
value: appState.zoom as NormalizedZoomValue,
translation: defaultAppState.zoom.translation,
}
: appState.zoom || defaultAppState.zoom,
};

View File

@ -227,10 +227,7 @@ export const renderScene = (
}
// Apply zoom
const zoomTranslationX = renderConfig.zoom.translation.x;
const zoomTranslationY = renderConfig.zoom.translation.y;
context.save();
context.translate(zoomTranslationX, zoomTranslationY);
context.scale(renderConfig.zoom.value, renderConfig.zoom.value);
// Grid
@ -238,14 +235,10 @@ export const renderScene = (
strokeGrid(
context,
appState.gridSize,
-Math.ceil(
zoomTranslationX / renderConfig.zoom.value / appState.gridSize,
) *
-Math.ceil(renderConfig.zoom.value / appState.gridSize) *
appState.gridSize +
(renderConfig.scrollX % appState.gridSize),
-Math.ceil(
zoomTranslationY / renderConfig.zoom.value / appState.gridSize,
) *
-Math.ceil(renderConfig.zoom.value / appState.gridSize) *
appState.gridSize +
(renderConfig.scrollY % appState.gridSize),
normalizedCanvasWidth / renderConfig.zoom.value,

View File

@ -18,4 +18,4 @@ export {
hasText,
getElementsAtPosition,
} from "./comparisons";
export { getNormalizedZoom, getNewZoom } from "./zoom";
export { getNormalizedZoom } from "./zoom";

View File

@ -41,14 +41,8 @@ export const centerScrollOn = ({
zoom: Zoom;
}) => {
return {
scrollX:
(viewportDimensions.width / 2) * (1 / zoom.value) -
scenePoint.x -
zoom.translation.x * (1 / zoom.value),
scrollY:
(viewportDimensions.height / 2) * (1 / zoom.value) -
scenePoint.y -
zoom.translation.y * (1 / zoom.value),
scrollX: (viewportDimensions.width / 2) * (1 / zoom.value) - scenePoint.x,
scrollY: (viewportDimensions.height / 2) * (1 / zoom.value) - scenePoint.y,
};
};

View File

@ -1,30 +1,41 @@
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 {
value: newZoomValue,
translation: {
x:
zoomOnViewportPoint.x -
canvasOffset.left -
(zoomOnViewportPoint.x - canvasOffset.left - prevZoom.translation.x) *
(newZoomValue / prevZoom.value),
y:
zoomOnViewportPoint.y -
canvasOffset.top -
(zoomOnViewportPoint.y - canvasOffset.top - prevZoom.translation.y) *
(newZoomValue / prevZoom.value),
},
};
};
import { AppState, NormalizedZoomValue } from "../types";
export const getNormalizedZoom = (zoom: number): NormalizedZoomValue => {
const normalizedZoom = parseFloat(zoom.toFixed(2));
const clampedZoom = Math.max(0.1, Math.min(normalizedZoom, 30));
return clampedZoom as NormalizedZoomValue;
};
export const getStateForZoom = (
{
viewportX,
viewportY,
nextZoom,
}: {
viewportX: number;
viewportY: number;
nextZoom: NormalizedZoomValue;
},
appState: AppState,
) => {
const appLayerX = viewportX - appState.offsetLeft;
const appLayerY = viewportY - appState.offsetTop;
const currentZoom = appState.zoom.value;
// get original scroll position without zoom
const baseScrollX = appState.scrollX + (appLayerX - appLayerX / currentZoom);
const baseScrollY = appState.scrollY + (appLayerY - appLayerY / currentZoom);
// get scroll offsets for target zoom level
const zoomOffsetScrollX = -(appLayerX - appLayerX / nextZoom);
const zoomOffsetScrollY = -(appLayerY - appLayerY / nextZoom);
return {
scrollX: baseScrollX + zoomOffsetScrollX,
scrollY: baseScrollY + zoomOffsetScrollY,
zoom: {
value: nextZoom,
},
};
};

View File

@ -72,10 +72,6 @@ Object {
"width": 200,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -242,10 +238,6 @@ Object {
"width": 200,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -563,10 +555,6 @@ Object {
"width": 200,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -884,10 +872,6 @@ Object {
"width": 200,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -1052,10 +1036,6 @@ Object {
"width": 200,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -1258,10 +1238,6 @@ Object {
"width": 200,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -1523,10 +1499,6 @@ Object {
"width": 200,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -1856,10 +1828,6 @@ Object {
"width": 200,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -2611,10 +2579,6 @@ Object {
"width": 200,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -2932,10 +2896,6 @@ Object {
"width": 200,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -3257,10 +3217,6 @@ Object {
"width": 200,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -3656,10 +3612,6 @@ Object {
"width": 200,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -3923,10 +3875,6 @@ Object {
"width": 200,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -4255,10 +4203,6 @@ Object {
"width": 200,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -4360,10 +4304,6 @@ Object {
"width": 200,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -4441,10 +4381,6 @@ Object {
"width": 200,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}

View File

@ -83,10 +83,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -572,10 +568,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -1043,10 +1035,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -1858,10 +1846,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -2075,10 +2059,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -2549,10 +2529,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -2809,10 +2785,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -2982,10 +2954,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -3441,10 +3409,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -3690,10 +3654,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -3904,10 +3864,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -4156,10 +4112,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -4419,10 +4371,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -4839,10 +4787,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -5123,10 +5067,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -5428,10 +5368,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -5621,10 +5557,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -5791,10 +5723,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -6272,10 +6200,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -6596,10 +6520,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -8723,10 +8643,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -9101,10 +9017,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -9362,10 +9274,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -9589,10 +9497,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -9875,10 +9779,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -10045,10 +9945,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -10215,10 +10111,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -10385,10 +10277,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -10585,10 +10473,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -10785,10 +10669,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -11003,10 +10883,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -11203,10 +11079,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -11373,10 +11245,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -11543,10 +11411,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -11743,10 +11607,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -11913,10 +11773,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -12142,10 +11998,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -12884,10 +12736,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -13123,7 +12971,7 @@ Object {
"pendingImageElement": null,
"previousSelectedElementIds": Object {},
"resizingElement": null,
"scrollX": -5.416666666666667,
"scrollX": -2.916666666666668,
"scrollY": 0,
"scrolledOutside": false,
"selectedElementIds": Object {
@ -13143,10 +12991,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0.4166666666666714,
"y": 0,
},
"value": 1,
},
}
@ -13246,10 +13090,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -13354,10 +13194,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -13533,10 +13369,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -13858,10 +13690,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -14077,10 +13905,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -14925,10 +14749,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -15032,10 +14852,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -15849,10 +15665,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -16269,10 +16081,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -16508,8 +16316,8 @@ Object {
"pendingImageElement": null,
"previousSelectedElementIds": Object {},
"resizingElement": null,
"scrollX": 11.046099290780141,
"scrollY": -5,
"scrollX": 10,
"scrollY": -10,
"scrolledOutside": false,
"selectedElementIds": Object {
"id0": true,
@ -16528,11 +16336,7 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": -59.425,
"y": -48.66347517730496,
},
"value": 1.99,
"value": 1,
},
}
`;
@ -16633,10 +16437,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -17148,10 +16948,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}
@ -17251,10 +17047,6 @@ Object {
"width": 1024,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}

View File

@ -415,16 +415,12 @@ describe("restoreAppState", () => {
);
expect(restoredAppState.zoom.value).toBe(10);
expect(restoredAppState.zoom.translation).toMatchObject(
getDefaultAppState().zoom.translation,
);
});
it("when the zoom of imported data state is not a number", () => {
const stubImportedAppState = getDefaultAppState();
stubImportedAppState.zoom = {
value: 10 as NormalizedZoomValue,
translation: { x: 5, y: 3 },
};
const stubLocalAppState = getDefaultAppState();

View File

@ -87,8 +87,8 @@ export class Keyboard {
}
export class Pointer {
private clientX = 0;
private clientY = 0;
public clientX = 0;
public clientY = 0;
constructor(
private readonly pointerType: "mouse" | "touch" | "pen",
@ -156,7 +156,7 @@ export class Pointer {
// absolute coords
// ---------------------------------------------------------------------------
moveTo(x: number, y: number) {
moveTo(x: number = this.clientX, y: number = this.clientY) {
this.clientX = x;
this.clientY = y;
fireEvent.pointerMove(GlobalTestState.canvas, this.getEvent());

View File

@ -67,10 +67,6 @@ Object {
"viewModeEnabled": false,
"zenModeEnabled": false,
"zoom": Object {
"translation": Object {
"x": 0,
"y": 0,
},
"value": 1,
},
}

View File

@ -287,22 +287,39 @@ describe("regression tests", () => {
});
it("two-finger scroll works", () => {
const startScrollY = h.state.scrollY;
finger1.down(50, 50);
finger2.down(60, 50);
// scroll horizontally vertically
finger1.up(0, -10);
finger2.up(0, -10);
const startScrollY = h.state.scrollY;
finger1.downAt(0, 0);
finger2.downAt(10, 0);
finger1.clientY -= 10;
finger2.clientY -= 10;
finger1.moveTo();
finger2.moveTo();
finger1.upAt();
finger2.upAt();
expect(h.state.scrollY).toBeLessThan(startScrollY);
// scroll horizontally
const startScrollX = h.state.scrollX;
finger1.restorePosition(50, 50);
finger2.restorePosition(50, 60);
finger1.down();
finger2.down();
finger1.up(10, 0);
finger2.up(10, 0);
finger1.downAt();
finger2.downAt();
finger1.clientX += 10;
finger2.clientX += 10;
finger1.moveTo();
finger2.moveTo();
finger1.upAt();
finger2.upAt();
expect(h.state.scrollX).toBeGreaterThan(startScrollX);
});

View File

@ -155,10 +155,6 @@ export type NormalizedZoomValue = number & { _brand: "normalizedZoom" };
export type Zoom = Readonly<{
value: NormalizedZoomValue;
translation: Readonly<{
x: number;
y: number;
}>;
}>;
export type PointerCoords = Readonly<{

View File

@ -223,8 +223,9 @@ export const viewportCoordsToSceneCoords = (
},
) => {
const invScale = 1 / zoom.value;
const x = (clientX - zoom.translation.x - offsetLeft) * invScale - scrollX;
const y = (clientY - zoom.translation.y - offsetTop) * invScale - scrollY;
const x = (clientX - offsetLeft) * invScale - scrollX;
const y = (clientY - offsetTop) * invScale - scrollY;
return { x, y };
};
@ -244,8 +245,8 @@ export const sceneCoordsToViewportCoords = (
scrollY: number;
},
) => {
const x = (sceneX + scrollX) * zoom.value + zoom.translation.x + offsetLeft;
const y = (sceneY + scrollY) * zoom.value + zoom.translation.y + offsetTop;
const x = (sceneX + scrollX) * zoom.value + offsetLeft;
const y = (sceneY + scrollY) * zoom.value + offsetTop;
return { x, y };
};