Fix issue with drag start using old positions on touch devices
This commit is contained in:
parent
edab7c85f1
commit
b6b68014ed
@ -91,14 +91,14 @@ function MapInteraction({
|
|||||||
onPinchEnd: () => {
|
onPinchEnd: () => {
|
||||||
onSelectedToolChange(previousSelectedToolRef.current);
|
onSelectedToolChange(previousSelectedToolRef.current);
|
||||||
},
|
},
|
||||||
onDragStart: () => {
|
onDrag: ({ first, last }) => {
|
||||||
interactionEmitter.emit("dragStart");
|
if (first) {
|
||||||
},
|
interactionEmitter.emit("dragStart");
|
||||||
onDrag: () => {
|
} else if (last) {
|
||||||
interactionEmitter.emit("drag");
|
interactionEmitter.emit("dragEnd");
|
||||||
},
|
} else {
|
||||||
onDragEnd: () => {
|
interactionEmitter.emit("drag");
|
||||||
interactionEmitter.emit("dragEnd");
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -21,131 +21,141 @@ function useStageInteraction(
|
|||||||
const pinchPreviousDistanceRef = useRef();
|
const pinchPreviousDistanceRef = useRef();
|
||||||
const pinchPreviousOriginRef = useRef();
|
const pinchPreviousOriginRef = useRef();
|
||||||
|
|
||||||
const bind = useGesture({
|
const bind = useGesture(
|
||||||
...gesture,
|
{
|
||||||
onWheelStart: (props) => {
|
...gesture,
|
||||||
const { event } = props;
|
onWheelStart: (props) => {
|
||||||
isInteractingWithCanvas.current =
|
const { event } = props;
|
||||||
event.target === layer.getCanvas()._canvas;
|
isInteractingWithCanvas.current =
|
||||||
gesture.onWheelStart && gesture.onWheelStart(props);
|
event.target === layer.getCanvas()._canvas;
|
||||||
},
|
gesture.onWheelStart && gesture.onWheelStart(props);
|
||||||
onWheel: (props) => {
|
},
|
||||||
const { event } = props;
|
onWheel: (props) => {
|
||||||
event.persist();
|
const { event } = props;
|
||||||
const { pixelY } = normalizeWheel(event);
|
event.persist();
|
||||||
if (preventInteraction || !isInteractingWithCanvas.current) {
|
const { pixelY } = normalizeWheel(event);
|
||||||
return;
|
if (preventInteraction || !isInteractingWithCanvas.current) {
|
||||||
}
|
return;
|
||||||
const newScale = Math.min(
|
}
|
||||||
Math.max(
|
const newScale = Math.min(
|
||||||
stageScale +
|
Math.max(
|
||||||
(pixelY * wheelZoomSpeed * stageScale) / window.innerHeight,
|
stageScale +
|
||||||
minZoom
|
(pixelY * wheelZoomSpeed * stageScale) / window.innerHeight,
|
||||||
),
|
minZoom
|
||||||
maxZoom
|
),
|
||||||
);
|
maxZoom
|
||||||
|
);
|
||||||
|
|
||||||
// Center on pointer
|
// Center on pointer
|
||||||
const pointer = stage.getPointerPosition();
|
const pointer = stage.getPointerPosition();
|
||||||
const newTranslate = {
|
|
||||||
x: pointer.x - ((pointer.x - stage.x()) / stageScale) * newScale,
|
|
||||||
y: pointer.y - ((pointer.y - stage.y()) / stageScale) * newScale,
|
|
||||||
};
|
|
||||||
|
|
||||||
stage.position(newTranslate);
|
|
||||||
stageTranslateRef.current = newTranslate;
|
|
||||||
|
|
||||||
onStageScaleChange(newScale);
|
|
||||||
gesture.onWheel && gesture.onWheel(props);
|
|
||||||
},
|
|
||||||
onPinchStart: (props) => {
|
|
||||||
const { event } = props;
|
|
||||||
isInteractingWithCanvas.current =
|
|
||||||
event.target === layer.getCanvas()._canvas;
|
|
||||||
const { da, origin } = props;
|
|
||||||
const [distance] = da;
|
|
||||||
const [originX, originY] = origin;
|
|
||||||
pinchPreviousDistanceRef.current = distance;
|
|
||||||
pinchPreviousOriginRef.current = { x: originX, y: originY };
|
|
||||||
gesture.onPinchStart && gesture.onPinchStart(props);
|
|
||||||
},
|
|
||||||
onPinch: (props) => {
|
|
||||||
if (preventInteraction || !isInteractingWithCanvas.current) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const { da, origin } = props;
|
|
||||||
const [distance] = da;
|
|
||||||
const [originX, originY] = origin;
|
|
||||||
|
|
||||||
// Apply scale
|
|
||||||
const distanceDelta = distance - pinchPreviousDistanceRef.current;
|
|
||||||
const originXDelta = originX - pinchPreviousOriginRef.current.x;
|
|
||||||
const originYDelta = originY - pinchPreviousOriginRef.current.y;
|
|
||||||
const newScale = Math.min(
|
|
||||||
Math.max(
|
|
||||||
stageScale + distanceDelta * touchZoomSpeed * stageScale,
|
|
||||||
minZoom
|
|
||||||
),
|
|
||||||
maxZoom
|
|
||||||
);
|
|
||||||
|
|
||||||
const canvasRect = layer.getCanvas()._canvas.getBoundingClientRect();
|
|
||||||
const relativeOrigin = {
|
|
||||||
x: originX - canvasRect.left,
|
|
||||||
y: originY - canvasRect.top,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Center on pinch origin
|
|
||||||
const centeredTranslate = {
|
|
||||||
x:
|
|
||||||
relativeOrigin.x -
|
|
||||||
((relativeOrigin.x - stage.x()) / stageScale) * newScale,
|
|
||||||
y:
|
|
||||||
relativeOrigin.y -
|
|
||||||
((relativeOrigin.y - stage.y()) / stageScale) * newScale,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Add pinch movement
|
|
||||||
const newTranslate = {
|
|
||||||
x: centeredTranslate.x + originXDelta,
|
|
||||||
y: centeredTranslate.y + originYDelta,
|
|
||||||
};
|
|
||||||
|
|
||||||
stage.position(newTranslate);
|
|
||||||
stageTranslateRef.current = newTranslate;
|
|
||||||
|
|
||||||
onStageScaleChange(newScale);
|
|
||||||
|
|
||||||
pinchPreviousDistanceRef.current = distance;
|
|
||||||
pinchPreviousOriginRef.current = { x: originX, y: originY };
|
|
||||||
gesture.onPinch && gesture.onPinch(props);
|
|
||||||
},
|
|
||||||
onDragStart: (props) => {
|
|
||||||
const { event } = props;
|
|
||||||
isInteractingWithCanvas.current =
|
|
||||||
event.target === layer.getCanvas()._canvas;
|
|
||||||
gesture.onDragStart && gesture.onDragStart(props);
|
|
||||||
},
|
|
||||||
onDrag: (props) => {
|
|
||||||
const { delta, pinching } = props;
|
|
||||||
if (preventInteraction || pinching || !isInteractingWithCanvas.current) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const [dx, dy] = delta;
|
|
||||||
const stageTranslate = stageTranslateRef.current;
|
|
||||||
if (tool === "pan") {
|
|
||||||
const newTranslate = {
|
const newTranslate = {
|
||||||
x: stageTranslate.x + dx,
|
x: pointer.x - ((pointer.x - stage.x()) / stageScale) * newScale,
|
||||||
y: stageTranslate.y + dy,
|
y: pointer.y - ((pointer.y - stage.y()) / stageScale) * newScale,
|
||||||
};
|
};
|
||||||
|
|
||||||
stage.position(newTranslate);
|
stage.position(newTranslate);
|
||||||
stage.draw();
|
|
||||||
stageTranslateRef.current = newTranslate;
|
stageTranslateRef.current = newTranslate;
|
||||||
}
|
|
||||||
gesture.onDrag && gesture.onDrag(props);
|
onStageScaleChange(newScale);
|
||||||
|
gesture.onWheel && gesture.onWheel(props);
|
||||||
|
},
|
||||||
|
onPinchStart: (props) => {
|
||||||
|
const { event } = props;
|
||||||
|
isInteractingWithCanvas.current =
|
||||||
|
event.target === layer.getCanvas()._canvas;
|
||||||
|
const { da, origin } = props;
|
||||||
|
const [distance] = da;
|
||||||
|
const [originX, originY] = origin;
|
||||||
|
pinchPreviousDistanceRef.current = distance;
|
||||||
|
pinchPreviousOriginRef.current = { x: originX, y: originY };
|
||||||
|
gesture.onPinchStart && gesture.onPinchStart(props);
|
||||||
|
},
|
||||||
|
onPinch: (props) => {
|
||||||
|
if (preventInteraction || !isInteractingWithCanvas.current) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const { da, origin } = props;
|
||||||
|
const [distance] = da;
|
||||||
|
const [originX, originY] = origin;
|
||||||
|
|
||||||
|
// Apply scale
|
||||||
|
const distanceDelta = distance - pinchPreviousDistanceRef.current;
|
||||||
|
const originXDelta = originX - pinchPreviousOriginRef.current.x;
|
||||||
|
const originYDelta = originY - pinchPreviousOriginRef.current.y;
|
||||||
|
const newScale = Math.min(
|
||||||
|
Math.max(
|
||||||
|
stageScale + distanceDelta * touchZoomSpeed * stageScale,
|
||||||
|
minZoom
|
||||||
|
),
|
||||||
|
maxZoom
|
||||||
|
);
|
||||||
|
|
||||||
|
const canvasRect = layer.getCanvas()._canvas.getBoundingClientRect();
|
||||||
|
const relativeOrigin = {
|
||||||
|
x: originX - canvasRect.left,
|
||||||
|
y: originY - canvasRect.top,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Center on pinch origin
|
||||||
|
const centeredTranslate = {
|
||||||
|
x:
|
||||||
|
relativeOrigin.x -
|
||||||
|
((relativeOrigin.x - stage.x()) / stageScale) * newScale,
|
||||||
|
y:
|
||||||
|
relativeOrigin.y -
|
||||||
|
((relativeOrigin.y - stage.y()) / stageScale) * newScale,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add pinch movement
|
||||||
|
const newTranslate = {
|
||||||
|
x: centeredTranslate.x + originXDelta,
|
||||||
|
y: centeredTranslate.y + originYDelta,
|
||||||
|
};
|
||||||
|
|
||||||
|
stage.position(newTranslate);
|
||||||
|
stageTranslateRef.current = newTranslate;
|
||||||
|
|
||||||
|
onStageScaleChange(newScale);
|
||||||
|
|
||||||
|
pinchPreviousDistanceRef.current = distance;
|
||||||
|
pinchPreviousOriginRef.current = { x: originX, y: originY };
|
||||||
|
gesture.onPinch && gesture.onPinch(props);
|
||||||
|
},
|
||||||
|
onDragStart: (props) => {
|
||||||
|
const { event } = props;
|
||||||
|
isInteractingWithCanvas.current =
|
||||||
|
event.target === layer.getCanvas()._canvas;
|
||||||
|
gesture.onDragStart && gesture.onDragStart(props);
|
||||||
|
},
|
||||||
|
onDrag: (props) => {
|
||||||
|
const { delta, pinching } = props;
|
||||||
|
if (
|
||||||
|
preventInteraction ||
|
||||||
|
pinching ||
|
||||||
|
!isInteractingWithCanvas.current
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const [dx, dy] = delta;
|
||||||
|
const stageTranslate = stageTranslateRef.current;
|
||||||
|
if (tool === "pan") {
|
||||||
|
const newTranslate = {
|
||||||
|
x: stageTranslate.x + dx,
|
||||||
|
y: stageTranslate.y + dy,
|
||||||
|
};
|
||||||
|
stage.position(newTranslate);
|
||||||
|
stage.draw();
|
||||||
|
stageTranslateRef.current = newTranslate;
|
||||||
|
}
|
||||||
|
gesture.onDrag && gesture.onDrag(props);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
{
|
||||||
|
// Fix drawing using old pointer end position on touch devices when drawing new shapes
|
||||||
|
drag: { delay: 300 },
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
return bind;
|
return bind;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user