139 lines
3.3 KiB
TypeScript
139 lines
3.3 KiB
TypeScript
import react, { useState } from 'react';
|
|
import Viewport from './Viewport';
|
|
|
|
interface MouseHandlerProperties {
|
|
boardSize: number;
|
|
shift: { x: number; y: number };
|
|
zoom: number;
|
|
}
|
|
|
|
const MouseHandler: react.FC<MouseHandlerProperties> = (
|
|
props: MouseHandlerProperties
|
|
) => {
|
|
const initialMouseState = {
|
|
down: false,
|
|
starting: { x: -1, y: -1 },
|
|
timestamp: 0,
|
|
};
|
|
|
|
const [mouseState, setMouseState] = useState(initialMouseState);
|
|
|
|
const [shift, setShift] = useState(props.shift);
|
|
const [zoom, setZoom] = useState(props.zoom);
|
|
|
|
console.log('MouseHandler, mouseState: ' + JSON.stringify(mouseState));
|
|
console.log(
|
|
'MouseHandler, shift: ' + JSON.stringify(shift) + ', zoom:' + zoom
|
|
);
|
|
|
|
const genericHandler = (event: any) => {
|
|
console.log(`Log - Event: ${event.type}`);
|
|
if (event.pageX !== undefined) {
|
|
console.log(
|
|
`Mouse : ${event.pageX}, ${event.pageY}, target: ${event.target}`
|
|
);
|
|
console.log(
|
|
`mouseState: ' ${JSON.stringify(mouseState)} (+${
|
|
Date.now() - mouseState.timestamp
|
|
}ms) `
|
|
);
|
|
return;
|
|
}
|
|
};
|
|
|
|
const mouseLeaveHandler = (event: any) => {
|
|
genericHandler(event);
|
|
setMouseState(initialMouseState);
|
|
};
|
|
|
|
const mouseDownHandler = (event: any) => {
|
|
genericHandler(event);
|
|
setMouseState({
|
|
down: true,
|
|
starting: { x: event.pageX, y: event.pageY },
|
|
timestamp: Date.now(),
|
|
});
|
|
};
|
|
|
|
const mouseUpHandler = (event: any) => {
|
|
genericHandler(event);
|
|
setMouseState(initialMouseState);
|
|
};
|
|
|
|
const mouseMoveHandler = (event: any) => {
|
|
if (mouseState.down && Date.now() - mouseState.timestamp > 5) {
|
|
genericHandler(event);
|
|
console.log(
|
|
`dispatch ${JSON.stringify({
|
|
x: event.pageX - mouseState.starting.x,
|
|
y: event.pageY - mouseState.starting.y,
|
|
})}`
|
|
);
|
|
setShift({
|
|
x: shift.x + (event.pageX - mouseState.starting.x),
|
|
y: shift.y + (event.pageY - mouseState.starting.y),
|
|
});
|
|
setMouseState({
|
|
down: true,
|
|
starting: {
|
|
x: event.pageX,
|
|
y: event.pageY,
|
|
},
|
|
timestamp: Date.now(),
|
|
});
|
|
}
|
|
};
|
|
|
|
const doScale = (x: number, y: number, factor: number) => {
|
|
setShift({
|
|
x: shift.x + (shift.x - x) * (factor - 1),
|
|
y: shift.y + (shift.y - y) * (factor - 1),
|
|
});
|
|
setZoom(zoom * factor);
|
|
};
|
|
|
|
const doubleClickHandler = (event: any) => {
|
|
genericHandler(event);
|
|
doScale(event.pageX, event.pageY, Math.SQRT2);
|
|
};
|
|
|
|
const initialWheelState = {
|
|
timestamp: 0,
|
|
};
|
|
|
|
const [wheelState, setWheelState] = useState(initialWheelState);
|
|
|
|
const wheelEventHandler = (event: any) => {
|
|
genericHandler(event);
|
|
if (
|
|
event.deltaMode === WheelEvent.DOM_DELTA_PIXEL &&
|
|
Date.now() - wheelState.timestamp > 100
|
|
) {
|
|
doScale(
|
|
event.pageX,
|
|
event.pageY,
|
|
event.deltaY < 0 ? Math.SQRT2 : Math.SQRT1_2
|
|
);
|
|
|
|
setWheelState({
|
|
timestamp: Date.now(),
|
|
});
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div
|
|
onMouseDown={mouseDownHandler}
|
|
onMouseMove={mouseMoveHandler}
|
|
onMouseUp={mouseUpHandler}
|
|
onMouseLeave={mouseLeaveHandler}
|
|
onDoubleClick={doubleClickHandler}
|
|
onWheel={wheelEventHandler}
|
|
>
|
|
<Viewport boardSize={props.boardSize} shift={shift} zoom={zoom} />
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default MouseHandler;
|