refactor: simplify zoom by removing zoom.translation
(#4477)
This commit is contained in:
parent
e4edda4555
commit
79d323fab1
@ -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;
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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:
|
||||
|
@ -261,7 +261,6 @@ export const restoreAppState = (
|
||||
typeof appState.zoom === "number"
|
||||
? {
|
||||
value: appState.zoom as NormalizedZoomValue,
|
||||
translation: defaultAppState.zoom.translation,
|
||||
}
|
||||
: appState.zoom || defaultAppState.zoom,
|
||||
};
|
||||
|
@ -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,
|
||||
|
@ -18,4 +18,4 @@ export {
|
||||
hasText,
|
||||
getElementsAtPosition,
|
||||
} from "./comparisons";
|
||||
export { getNormalizedZoom, getNewZoom } from "./zoom";
|
||||
export { getNormalizedZoom } from "./zoom";
|
||||
|
@ -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,
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
@ -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,
|
||||
},
|
||||
}
|
||||
|
@ -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,
|
||||
},
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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());
|
||||
|
@ -67,10 +67,6 @@ Object {
|
||||
"viewModeEnabled": false,
|
||||
"zenModeEnabled": false,
|
||||
"zoom": Object {
|
||||
"translation": Object {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
},
|
||||
"value": 1,
|
||||
},
|
||||
}
|
||||
|
@ -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);
|
||||
});
|
||||
|
||||
|
@ -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<{
|
||||
|
@ -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 };
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user