Open manuel-minniti opened 1 year ago
I wonder if this could be solved with simply changing
const isPanningAction = touches.length === 1;
to
const isPanningAction = touches.length >= 1;
+1 for this feature.
Did anyone find a workaround without changing the package's codebase?
I manage to solve it, here are the changes:
In file: react-zoom-pan-pinch/src/core/instance.core.ts Add this inside the class ZoomPanPinch:
public pinchLastCenterX: number = null;
public pinchLastCenterY: number = null;
Then change this file: react-zoom-pan-pinch/src/core/pinch/pinch.logic.ts
/* eslint-disable no-param-reassign */
import { ReactZoomPanPinchContext } from "../../models";
import { handleCancelAnimation } from "../animations/animations.utils";
import { handleAlignToScaleBounds } from "../zoom/zoom.logic";
import {
calculatePinchZoom,
calculateTouchMidPoint,
getTouchDistance,
} from "./pinch.utils";
import { getMouseBoundedPosition, handleCalculateBounds } from "../bounds/bounds.utils";
import { handleCalculateZoomPositions } from "../zoom/zoom.utils";
import { getPaddingValue } from "../pan/panning.utils";
const getTouchCenter = (event: TouchEvent) => {
let totalX = 0;
let totalY = 0;
// Sum up the positions of all touches
for (let i = 0; i < 2; i++) {
totalX += event.touches[i].clientX;
totalY += event.touches[i].clientY;
}
// Calculate the average position
const x = totalX / 2;
const y = totalY / 2;
return { x, y };
}
export const handlePinchStart = (
contextInstance: ReactZoomPanPinchContext,
event: TouchEvent,
): void => {
const distance = getTouchDistance(event);
contextInstance.pinchStartDistance = distance;
contextInstance.lastDistance = distance;
contextInstance.pinchStartScale = contextInstance.transformState.scale;
contextInstance.isPanning = false;
const center = getTouchCenter(event);
contextInstance.pinchLastCenterX = center.x;
contextInstance.pinchLastCenterY = center.y;
handleCancelAnimation(contextInstance);
};
export const handlePinchZoom = (
contextInstance: ReactZoomPanPinchContext,
event: TouchEvent,
): void => {
const { contentComponent, pinchStartDistance, wrapperComponent } = contextInstance;
const { scale } = contextInstance.transformState;
const { limitToBounds, centerZoomedOut, zoomAnimation, alignmentAnimation } =
contextInstance.setup;
const { disabled, size } = zoomAnimation;
// if one finger starts from outside of wrapper
if (pinchStartDistance === null || !contentComponent) return;
const midPoint = calculateTouchMidPoint(event, scale, contentComponent);
// if touches goes off of the wrapper element
if (!Number.isFinite(midPoint.x) || !Number.isFinite(midPoint.y)) return;
const currentDistance = getTouchDistance(event);
const newScale = calculatePinchZoom(contextInstance, currentDistance);
const center = getTouchCenter(event);
// pan should be scale invariant.
const panX = (center.x - contextInstance.pinchLastCenterX);
const panY = (center.y - contextInstance.pinchLastCenterY);
if (
newScale === scale &&
0 == panX &&
0 == panY
)
return;
contextInstance.pinchLastCenterX = center.x;
contextInstance.pinchLastCenterY = center.y;
const bounds = handleCalculateBounds(contextInstance, newScale);
const isPaddingDisabled = disabled || size === 0 || centerZoomedOut;
const isLimitedToBounds = limitToBounds && isPaddingDisabled;
const { x, y } = handleCalculateZoomPositions(
contextInstance,
midPoint.x,
midPoint.y,
newScale,
bounds,
isLimitedToBounds,
);
contextInstance.pinchMidpoint = midPoint;
contextInstance.lastDistance = currentDistance;
const { sizeX, sizeY } = alignmentAnimation;
const paddingValueX = getPaddingValue(contextInstance, sizeX);
const paddingValueY = getPaddingValue(contextInstance, sizeY);
const newPositionX = x + panX;
const newPositionY = y + panY;
const { x: finalX, y: finalY } = getMouseBoundedPosition(
newPositionX,
newPositionY,
bounds,
limitToBounds,
paddingValueX,
paddingValueY,
wrapperComponent,
);
contextInstance.setTransformState(newScale, finalX, finalY);
};
export const handlePinchStop = (
contextInstance: ReactZoomPanPinchContext,
): void => {
const { pinchMidpoint } = contextInstance;
contextInstance.velocity = null;
contextInstance.lastDistance = null;
contextInstance.pinchMidpoint = null;
contextInstance.pinchStartScale = null;
contextInstance.pinchStartDistance = null;
handleAlignToScaleBounds(contextInstance, pinchMidpoint?.x, pinchMidpoint?.y);
};
Is your feature request related to a problem? Please describe. Is it possible to do panning while pinch zooming? It only seems to do one at a time.
Describe the solution you'd like Being able to do panning while pinch zooming.
Describe alternatives you've considered This might be possible with a custom transform function.
This is especially useful for mobile devices – think of Google Maps for example.
Most likely related to the following code:
It seems that the corresponding action is determined by the number of touches.