feat: center constrained area on zoom out

This commit is contained in:
Arnošt Pleskot 2023-07-03 22:34:26 +02:00
parent a8158691b7
commit 209934c90a
No known key found for this signature in database

View File

@ -7640,6 +7640,7 @@ class App extends React.Component<AppProps, AppState> {
) => { ) => {
this.setState({ this.setState({
scrollConstraints, scrollConstraints,
viewModeEnabled: !!scrollConstraints,
}); });
}; };
@ -7661,25 +7662,42 @@ class App extends React.Component<AppProps, AppState> {
return nextState; return nextState;
} }
// Calculate scaled width and height // Calculate maximum zoom for both X and Y axis based on width and height of viewport and scrollable area
const scaledWidth = width / zoom.value;
const scaledHeight = height / zoom.value;
const maxZoomX = width / scrollConstraints.width; const maxZoomX = width / scrollConstraints.width;
const maxZoomY = height / scrollConstraints.height; const maxZoomY = height / scrollConstraints.height;
// The smallest zoom out of maxZoomX and maxZoomY is our zoom limit
const zoomLimit = Math.min(maxZoomX, maxZoomY);
// Set default constrainedScrollX and constrainedScrollY values // Set default constrainedScrollX and constrainedScrollY values
let constrainedScrollX = scrollX; let constrainedScrollX = scrollX;
let constrainedScrollY = scrollY; let constrainedScrollY = scrollY;
let constrainedZoom = zoom; let constrainedZoom = zoom;
// Function to adjust scroll position for centered view depending on the zoom value
const adjustScrollForCenteredView = (zoomValue: number) => {
// If zoom value is less than or equal to maxZoomX, adjust scrollX to ensure the view is centered on the X axis
if (zoomValue <= maxZoomX) {
const centeredScrollX =
(scrollConstraints.width - width / zoomValue) / -2;
constrainedScrollX = scrollConstraints.x + centeredScrollX;
}
// If zoom value is less than or equal to maxZoomY, adjust scrollY to ensure the view is centered on the Y axis
if (zoomValue <= maxZoomY) {
const centeredScrollY =
(scrollConstraints.height - height / zoomValue) / -2;
constrainedScrollY = scrollConstraints.y + centeredScrollY;
}
};
// If scrollX is part of the nextState, constrain it within the scroll constraints // If scrollX is part of the nextState, constrain it within the scroll constraints
if ("scrollX" in nextState) { if ("scrollX" in nextState) {
constrainedScrollX = Math.min( constrainedScrollX = Math.min(
scrollConstraints.x, scrollConstraints.x,
Math.max( Math.max(
nextState.scrollX, nextState.scrollX,
scrollConstraints.x - scrollConstraints.width + scaledWidth, scrollConstraints.x - scrollConstraints.width + width / zoom.value,
), ),
); );
} }
@ -7690,19 +7708,26 @@ class App extends React.Component<AppProps, AppState> {
scrollConstraints.y, scrollConstraints.y,
Math.max( Math.max(
nextState.scrollY, nextState.scrollY,
scrollConstraints.y - scrollConstraints.height + scaledHeight, scrollConstraints.y - scrollConstraints.height + height / zoom.value,
), ),
); );
} }
// If zoom is part of the nextState, constrain it within the scroll constraints // If zoom is part of the nextState, constrain it within the scroll constraints and adjust for centered view
if ("zoom" in nextState) { if (
const zoomLimit = Math.min(maxZoomX, maxZoomY); "zoom" in nextState &&
typeof nextState.zoom === "object" &&
nextState.zoom !== null
) {
constrainedZoom = { constrainedZoom = {
value: getNormalizedZoom(Math.max(nextState.zoom.value, zoomLimit)), value: getNormalizedZoom(Math.max(nextState.zoom.value, zoomLimit)),
}; };
} }
// Call function to adjust scroll position for centered view depending on the current zoom value
adjustScrollForCenteredView(constrainedZoom.value);
// Return the nextState with constrained scrollX, scrollY, and zoom values
return { return {
...nextState, ...nextState,
scrollX: constrainedScrollX, scrollX: constrainedScrollX,