fix jumping/flashing when zooming in or out too quickly
This commit is contained in:
parent
bc6cc83b1e
commit
84c396aec2
@ -531,6 +531,7 @@ import type { Action, ActionResult } from "../actions/types";
|
|||||||
import {
|
import {
|
||||||
constrainScrollState,
|
constrainScrollState,
|
||||||
calculateConstrainedScrollCenter,
|
calculateConstrainedScrollCenter,
|
||||||
|
areCanvasViewsClose,
|
||||||
} from "../scene/scrollConstraints";
|
} from "../scene/scrollConstraints";
|
||||||
|
|
||||||
const AppContext = React.createContext<AppClassProperties>(null!);
|
const AppContext = React.createContext<AppClassProperties>(null!);
|
||||||
@ -2975,20 +2976,27 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
const newState = constrainScrollState(this.state, {
|
const newState = constrainScrollState(this.state, {
|
||||||
allowOverscroll: false,
|
allowOverscroll: false,
|
||||||
});
|
});
|
||||||
|
const fromValues = {
|
||||||
|
scrollX: this.state.scrollX,
|
||||||
|
scrollY: this.state.scrollY,
|
||||||
|
zoom: this.state.zoom.value,
|
||||||
|
};
|
||||||
|
const toValues = {
|
||||||
|
scrollX: newState.scrollX,
|
||||||
|
scrollY: newState.scrollY,
|
||||||
|
zoom: newState.zoom.value,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (areCanvasViewsClose(fromValues, toValues)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scrollConstraintsAnimationTimeout) {
|
||||||
|
clearTimeout(scrollConstraintsAnimationTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
scrollConstraintsAnimationTimeout = setTimeout(() => {
|
scrollConstraintsAnimationTimeout = setTimeout(() => {
|
||||||
this.cancelInProgressAnimation?.();
|
this.cancelInProgressAnimation?.();
|
||||||
const fromValues = {
|
|
||||||
scrollX: this.state.scrollX,
|
|
||||||
scrollY: this.state.scrollY,
|
|
||||||
zoom: this.state.zoom.value,
|
|
||||||
};
|
|
||||||
const toValues = {
|
|
||||||
scrollX: newState.scrollX,
|
|
||||||
scrollY: newState.scrollY,
|
|
||||||
zoom: newState.zoom.value,
|
|
||||||
};
|
|
||||||
|
|
||||||
this.animateToConstrainedArea(fromValues, toValues);
|
this.animateToConstrainedArea(fromValues, toValues);
|
||||||
}, 200);
|
}, 200);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import { isShallowEqual } from "@excalidraw/common";
|
import { isShallowEqual } from "@excalidraw/common";
|
||||||
import { AppState, ScrollConstraints } from "../types";
|
import {
|
||||||
|
AnimateTranslateCanvasValues,
|
||||||
|
AppState,
|
||||||
|
ScrollConstraints,
|
||||||
|
} from "../types";
|
||||||
import { getNormalizedZoom } from "./normalize";
|
import { getNormalizedZoom } from "./normalize";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -18,14 +22,13 @@ import { getNormalizedZoom } from "./normalize";
|
|||||||
*
|
*
|
||||||
* const { scrollX, scrollY, zoom } = this.calculateConstrainedScrollCenter(scrollConstraints, { scrollX, scrollY });
|
* const { scrollX, scrollY, zoom } = this.calculateConstrainedScrollCenter(scrollConstraints, { scrollX, scrollY });
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
type CanvasTranslate = Pick<AppState, "scrollX" | "scrollY" | "zoom">;
|
||||||
|
|
||||||
export const calculateConstrainedScrollCenter = (
|
export const calculateConstrainedScrollCenter = (
|
||||||
state: AppState,
|
state: AppState,
|
||||||
{ scrollX, scrollY }: Pick<AppState, "scrollX" | "scrollY">,
|
{ scrollX, scrollY }: Pick<AppState, "scrollX" | "scrollY">,
|
||||||
): {
|
): CanvasTranslate => {
|
||||||
scrollX: AppState["scrollX"];
|
|
||||||
scrollY: AppState["scrollY"];
|
|
||||||
zoom: AppState["zoom"];
|
|
||||||
} => {
|
|
||||||
const {
|
const {
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
@ -352,7 +355,7 @@ const constrainScrollValues = ({
|
|||||||
maxScrollY: number;
|
maxScrollY: number;
|
||||||
minScrollY: number;
|
minScrollY: number;
|
||||||
constrainedZoom: AppState["zoom"];
|
constrainedZoom: AppState["zoom"];
|
||||||
}) => {
|
}): CanvasTranslate => {
|
||||||
const constrainedScrollX = Math.min(
|
const constrainedScrollX = Math.min(
|
||||||
maxScrollX,
|
maxScrollX,
|
||||||
Math.max(scrollX, minScrollX),
|
Math.max(scrollX, minScrollX),
|
||||||
@ -389,7 +392,7 @@ const alignScrollConstraints = (
|
|||||||
* Determines whether the current viewport is outside the constrained area defined in the AppState.
|
* Determines whether the current viewport is outside the constrained area defined in the AppState.
|
||||||
*
|
*
|
||||||
* @param state - The application state containing scroll, zoom, and constraint information.
|
* @param state - The application state containing scroll, zoom, and constraint information.
|
||||||
* @returns True if the viewport is outside the constrained area; otherwise undefined.
|
* @returns True if the viewport is outside the constrained area, false otherwise.
|
||||||
*/
|
*/
|
||||||
const isViewportOutsideOfConstrainedArea = (state: AppState) => {
|
const isViewportOutsideOfConstrainedArea = (state: AppState) => {
|
||||||
if (!state.scrollConstraints) {
|
if (!state.scrollConstraints) {
|
||||||
@ -521,3 +524,15 @@ export const constrainScrollState = (
|
|||||||
...constrainedValues,
|
...constrainedValues,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const areCanvasViewsClose = (
|
||||||
|
from: AnimateTranslateCanvasValues,
|
||||||
|
to: AnimateTranslateCanvasValues,
|
||||||
|
): boolean => {
|
||||||
|
const threshold = 0.1; // Adjust based on your needs
|
||||||
|
return (
|
||||||
|
Math.abs(from.scrollX - to.scrollX) < threshold &&
|
||||||
|
Math.abs(from.scrollY - to.scrollY) < threshold &&
|
||||||
|
Math.abs(from.zoom - to.zoom) < threshold
|
||||||
|
);
|
||||||
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user