118 lines
3.3 KiB
TypeScript
118 lines
3.3 KiB
TypeScript
import react, { useCallback, useState } from 'react';
|
|
|
|
import _ from 'lodash';
|
|
|
|
import { Point } from './viewport';
|
|
|
|
interface DoubleTouchHandlerProps {
|
|
updateZoom: (zoomFactor: number, center: Point) => void;
|
|
children: any;
|
|
}
|
|
|
|
const DoubleTouchHandler: react.FC<DoubleTouchHandlerProps> = (
|
|
props: DoubleTouchHandlerProps
|
|
) => {
|
|
const initialTouchState = {
|
|
state: 'up',
|
|
touches: [
|
|
{ x: -1, y: -1 },
|
|
{ x: -1, y: -1 },
|
|
],
|
|
distance: -1,
|
|
initialZoom: 1,
|
|
};
|
|
|
|
const [touchState, setTouchState] = useState(initialTouchState);
|
|
|
|
console.log('DoubleTouchHandler, touchState: ' + JSON.stringify(touchState));
|
|
|
|
const genericHandler = (event: any) => {
|
|
console.log('Log - Event: ' + event.type);
|
|
if (event.type.startsWith('touch')) {
|
|
if (event.touches.length > 1) {
|
|
console.log(
|
|
`${event.touches.length} touches, (${event.touches[0].pageX}, ${event.touches[0].pageY}), (${event.touches[1].pageX}, ${event.touches[1].pageY})`
|
|
);
|
|
}
|
|
|
|
console.log('touchState: ' + JSON.stringify(touchState));
|
|
return;
|
|
}
|
|
};
|
|
const touchCancelHandler = (event: any) => {
|
|
genericHandler(event);
|
|
throtteledTouchMoveHandler.cancel();
|
|
setTouchState(initialTouchState);
|
|
};
|
|
|
|
const touchStartHandler = (event: any) => {
|
|
genericHandler(event);
|
|
if (event.touches.length === 2) {
|
|
setTouchState({
|
|
state: 'double',
|
|
touches: [
|
|
{ x: event.touches[0].pageX, y: event.touches[0].pageY },
|
|
{ x: event.touches[1].pageX, y: event.touches[1].pageY },
|
|
],
|
|
distance: Math.sqrt(
|
|
(event.touches[0].pageX - event.touches[1].pageX) ** 2 +
|
|
(event.touches[0].pageY - event.touches[1].pageY) ** 2
|
|
),
|
|
initialZoom: 1,
|
|
});
|
|
}
|
|
};
|
|
|
|
const touchEndHandler = (event: any) => {
|
|
genericHandler(event);
|
|
setTouchState(initialTouchState);
|
|
throtteledTouchMoveHandler.cancel();
|
|
};
|
|
|
|
const touchMoveHandler = (event: any) => {
|
|
if (touchState.state === 'double') {
|
|
if (event.touches.length === 2) {
|
|
genericHandler(event);
|
|
const newDistance = Math.sqrt(
|
|
(event.touches[0].pageX - event.touches[1].pageX) ** 2 +
|
|
(event.touches[0].pageY - event.touches[1].pageY) ** 2
|
|
);
|
|
const factor = newDistance / touchState.distance;
|
|
console.log(`+++++++++ ZOOM Factor is ${factor} ++++++++++`);
|
|
setTouchState({
|
|
state: 'double',
|
|
touches: [
|
|
{ x: event.touches[0].pageX, y: event.touches[0].pageY },
|
|
{ x: event.touches[1].pageX, y: event.touches[1].pageY },
|
|
],
|
|
distance: touchState.distance,
|
|
initialZoom: 1,
|
|
});
|
|
props.updateZoom(factor, {
|
|
x: (event.touches[0].pageX + event.touches[1].pageX) / 2,
|
|
y: (event.touches[0].pageY + event.touches[1].pageY) / 2,
|
|
});
|
|
}
|
|
}
|
|
};
|
|
|
|
const throtteledTouchMoveHandler = useCallback(
|
|
_.throttle(touchMoveHandler, 100),
|
|
[touchState.state]
|
|
);
|
|
|
|
return (
|
|
<div
|
|
className='viewport single-touch-handler'
|
|
onTouchStart={touchStartHandler}
|
|
onTouchMove={throtteledTouchMoveHandler}
|
|
onTouchEnd={touchEndHandler}
|
|
onTouchCancel={touchCancelHandler}
|
|
>
|
|
{props.children}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default DoubleTouchHandler;
|