Figuring out theright geometry for scaling and translating...

This commit is contained in:
Eric van der Vlist 2022-09-10 15:48:02 +02:00
parent c929c6758d
commit 38183bb5fe
5 changed files with 35 additions and 23 deletions

View File

@ -6,6 +6,7 @@ import { Point } from './viewport';
interface DoubleTouchHandlerProps { interface DoubleTouchHandlerProps {
updateZoom: (zoomFactor: number, center: Point) => void; updateZoom: (zoomFactor: number, center: Point) => void;
updateShift: (shiftDelta: Point) => void;
children: any; children: any;
} }
@ -88,10 +89,19 @@ const DoubleTouchHandler: react.FC<DoubleTouchHandlerProps> = (
distance: touchState.distance, distance: touchState.distance,
initialZoom: 1, initialZoom: 1,
}); });
props.updateZoom(factor, { const previousCenter = {
x: (touchState.touches[0].x + touchState.touches[1].x) / 2,
y: (touchState.touches[0].y + touchState.touches[1].y) / 2,
};
const currentCenter = {
x: (event.touches[0].pageX + event.touches[1].pageX) / 2, x: (event.touches[0].pageX + event.touches[1].pageX) / 2,
y: (event.touches[0].pageY + event.touches[1].pageY) / 2, y: (event.touches[0].pageY + event.touches[1].pageY) / 2,
}); };
props.updateZoom(factor, currentCenter);
// props.updateShift({
// x: currentCenter.x - previousCenter.x,
// y: currentCenter.y - previousCenter.y,
// });
} }
} }
}; };
@ -103,7 +113,7 @@ const DoubleTouchHandler: react.FC<DoubleTouchHandlerProps> = (
return ( return (
<div <div
className='viewport single-touch-handler' className='viewport double-touch-handler'
onTouchStart={touchStartHandler} onTouchStart={touchStartHandler}
onTouchMove={throtteledTouchMoveHandler} onTouchMove={throtteledTouchMoveHandler}
onTouchEnd={touchEndHandler} onTouchEnd={touchEndHandler}

View File

@ -18,7 +18,7 @@ const Layer: react.FC<{
<div <div
className='background' className='background'
style={{ style={{
transform: `translate(${-props.shift.x}px, ${-props.shift.y}px) scale(${ transform: `translate(${props.shift.x}px, ${props.shift.y}px) scale(${
props.zoom props.zoom
})`, })`,
}} }}

View File

@ -6,13 +6,13 @@ import { Point } from './viewport';
interface MouseHandlerProps { interface MouseHandlerProps {
updateShift: (shiftDelta: Point) => void; updateShift: (shiftDelta: Point) => void;
updateZoom: (zoomFactor: number, center: Point) => void;
children: any; children: any;
} }
const MouseHandler: react.FC<MouseHandlerProps> = ( const MouseHandler: react.FC<MouseHandlerProps> = (
props: MouseHandlerProps props: MouseHandlerProps
) => { ) => {
const initialMouseState = { const initialMouseState = {
down: false, down: false,
starting: { x: -1, y: -1 }, starting: { x: -1, y: -1 },
@ -24,7 +24,7 @@ const MouseHandler: react.FC<MouseHandlerProps> = (
const genericHandler = (event: any) => { const genericHandler = (event: any) => {
console.log('Log - Event: ' + event.type); console.log('Log - Event: ' + event.type);
if (event.type.startsWith('mouse')) { if (event.pageX !== undefined) {
console.log(`Mouse : ${event.pageX}, ${event.pageY}`); console.log(`Mouse : ${event.pageX}, ${event.pageY}`);
console.log('mouseState: ' + JSON.stringify(mouseState)); console.log('mouseState: ' + JSON.stringify(mouseState));
return; return;
@ -38,8 +38,8 @@ const MouseHandler: react.FC<MouseHandlerProps> = (
}; };
const mouseDownHandler = (event: any) => { const mouseDownHandler = (event: any) => {
genericHandler(event);
event.preventDefault(); event.preventDefault();
genericHandler(event);
setMouseState({ setMouseState({
down: true, down: true,
starting: { x: event.pageX, y: event.pageY }, starting: { x: event.pageX, y: event.pageY },
@ -57,8 +57,8 @@ const MouseHandler: react.FC<MouseHandlerProps> = (
if (mouseState.down) { if (mouseState.down) {
genericHandler(event); genericHandler(event);
props.updateShift({ props.updateShift({
x: mouseState.starting.x - event.pageX, x: event.pageX - mouseState.starting.x,
y: mouseState.starting.y - event.pageY, y: event.pageY - mouseState.starting.y,
}); });
setMouseState({ setMouseState({
down: true, down: true,
@ -75,13 +75,19 @@ const MouseHandler: react.FC<MouseHandlerProps> = (
[mouseState.down] [mouseState.down]
); );
const doubleClickHandler = (event: any) => {
genericHandler(event);
props.updateZoom(2, { x: event.pageX, y: event.pageY });
};
return ( return (
<div <div
className='viewport' className='viewport mouse-handler'
onMouseDown={mouseDownHandler} onMouseDown={mouseDownHandler}
onMouseMove={throtteledMouseMoveHandler} onMouseMove={throtteledMouseMoveHandler}
onMouseUp={mouseUpHandler} onMouseUp={mouseUpHandler}
onMouseLeave={mouseLeaveHandler} onMouseLeave={mouseLeaveHandler}
onDoubleClick={doubleClickHandler}
> >
{props.children} {props.children}
</div> </div>

View File

@ -64,8 +64,8 @@ const SingleTouchHandler: react.FC<SingleTouchHandlerProps> = (
if (event.touches.length === 1) { if (event.touches.length === 1) {
genericHandler(event); genericHandler(event);
props.updateShift({ props.updateShift({
x: touchState.touch.x - event.touches[0].pageX, x: event.touches[0].pageX - touchState.touch.x,
y: touchState.touch.y - event.touches[0].pageY, y: event.touches[0].pageY - touchState.touch.y,
}); });
setTouchState({ setTouchState({
state: 'pointer', state: 'pointer',
@ -85,7 +85,7 @@ const SingleTouchHandler: react.FC<SingleTouchHandlerProps> = (
return ( return (
<div <div
className='viewport' className='viewport single-touch-handler'
onTouchStart={touchStartHandler} onTouchStart={touchStartHandler}
onTouchMove={throtteledTouchMoveHandler} onTouchMove={throtteledTouchMoveHandler}
onTouchEnd={touchEndHandler} onTouchEnd={touchEndHandler}

View File

@ -41,22 +41,18 @@ const Viewport: react.FC<ViewportProps> = (props: ViewportProps) => {
const updateZoom = (zoomFactor: number, center: Point) => { const updateZoom = (zoomFactor: number, center: Point) => {
const newZoom = zoom * zoomFactor; const newZoom = zoom * zoomFactor;
setZoom(newZoom); updateShift({
setShift({ x: (shift.x - center.x) * (zoomFactor - 1),
x: shift.x + center.x / zoom - center.x / newZoom, y: (shift.y - center.y) * (zoomFactor - 1),
y: shift.y + center.y / zoom - center.y / newZoom,
}); });
// setShift({ setZoom(newZoom);
// x: shift.x + 1440 / 2 / zoom - window.innerWidth / 2 / newZoom,
// y: shift.y + 2904 / 2 / zoom - window.innerHeight / 2 / newZoom,
// });
}; };
return ( return (
<div className='viewport'> <div className='viewport'>
<MouseHandler updateShift={updateShift}> <MouseHandler updateShift={updateShift} updateZoom={updateZoom}>
<SingleTouchHandler updateShift={updateShift}> <SingleTouchHandler updateShift={updateShift}>
<DoubleTouchHandler updateZoom={updateZoom}> <DoubleTouchHandler updateZoom={updateZoom} updateShift={updateShift}>
<Layer shift={shift} zoom={zoom}> <Layer shift={shift} zoom={zoom}>
{props.children} {props.children}
</Layer> </Layer>