1
This commit is contained in:
+116
@@ -0,0 +1,116 @@
|
||||
import { warning } from "@rc-component/util/es/warning";
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import getFixScaleEleTransPosition from "../getFixScaleEleTransPosition";
|
||||
import { BASE_SCALE_RATIO, WHEEL_MAX_SCALE_RATIO } from "../previewConfig";
|
||||
export default function useMouseEvent(imgRef, movable, open, scaleStep, transform, updateTransform, dispatchZoomChange) {
|
||||
const {
|
||||
rotate,
|
||||
scale,
|
||||
x,
|
||||
y
|
||||
} = transform;
|
||||
const [isMoving, setMoving] = useState(false);
|
||||
const startPositionInfo = useRef({
|
||||
diffX: 0,
|
||||
diffY: 0,
|
||||
transformX: 0,
|
||||
transformY: 0
|
||||
});
|
||||
const onMouseDown = event => {
|
||||
// Only allow main button
|
||||
if (!movable || event.button !== 0) return;
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
startPositionInfo.current = {
|
||||
diffX: event.pageX - x,
|
||||
diffY: event.pageY - y,
|
||||
transformX: x,
|
||||
transformY: y
|
||||
};
|
||||
setMoving(true);
|
||||
};
|
||||
const onMouseMove = event => {
|
||||
if (open && isMoving) {
|
||||
updateTransform({
|
||||
x: event.pageX - startPositionInfo.current.diffX,
|
||||
y: event.pageY - startPositionInfo.current.diffY
|
||||
}, 'move');
|
||||
}
|
||||
};
|
||||
const onMouseUp = () => {
|
||||
if (open && isMoving) {
|
||||
setMoving(false);
|
||||
|
||||
/** No need to restore the position when the picture is not moved, So as not to interfere with the click */
|
||||
const {
|
||||
transformX,
|
||||
transformY
|
||||
} = startPositionInfo.current;
|
||||
const hasChangedPosition = x !== transformX && y !== transformY;
|
||||
if (!hasChangedPosition) return;
|
||||
const width = imgRef.current.offsetWidth * scale;
|
||||
const height = imgRef.current.offsetHeight * scale;
|
||||
// eslint-disable-next-line @typescript-eslint/no-shadow
|
||||
const {
|
||||
left,
|
||||
top
|
||||
} = imgRef.current.getBoundingClientRect();
|
||||
const isRotate = rotate % 180 !== 0;
|
||||
const fixState = getFixScaleEleTransPosition(isRotate ? height : width, isRotate ? width : height, left, top);
|
||||
if (fixState) {
|
||||
updateTransform({
|
||||
...fixState
|
||||
}, 'dragRebound');
|
||||
}
|
||||
}
|
||||
};
|
||||
const onWheel = event => {
|
||||
if (!open || event.deltaY == 0) return;
|
||||
// Scale ratio depends on the deltaY size
|
||||
const scaleRatio = Math.abs(event.deltaY / 100);
|
||||
// Limit the maximum scale ratio
|
||||
const mergedScaleRatio = Math.min(scaleRatio, WHEEL_MAX_SCALE_RATIO);
|
||||
// Scale the ratio each time
|
||||
let ratio = BASE_SCALE_RATIO + mergedScaleRatio * scaleStep;
|
||||
if (event.deltaY > 0) {
|
||||
ratio = BASE_SCALE_RATIO / ratio;
|
||||
}
|
||||
dispatchZoomChange(ratio, 'wheel', event.clientX, event.clientY);
|
||||
};
|
||||
useEffect(() => {
|
||||
if (movable) {
|
||||
window.addEventListener('mouseup', onMouseUp, false);
|
||||
window.addEventListener('mousemove', onMouseMove, false);
|
||||
try {
|
||||
// Resolve if in iframe lost event
|
||||
/* istanbul ignore next */
|
||||
if (window.top !== window.self) {
|
||||
window.top.addEventListener('mouseup', onMouseUp, false);
|
||||
window.top.addEventListener('mousemove', onMouseMove, false);
|
||||
}
|
||||
} catch (error) {
|
||||
/* istanbul ignore next */
|
||||
warning(false, `[rc-image] ${error}`);
|
||||
}
|
||||
}
|
||||
return () => {
|
||||
window.removeEventListener('mouseup', onMouseUp);
|
||||
window.removeEventListener('mousemove', onMouseMove);
|
||||
|
||||
/* istanbul ignore next */
|
||||
try {
|
||||
window.top?.removeEventListener('mouseup', onMouseUp);
|
||||
window.top?.removeEventListener('mousemove', onMouseMove);
|
||||
} catch (error) {
|
||||
// Do nothing
|
||||
}
|
||||
};
|
||||
}, [open, isMoving, x, y, rotate, movable]);
|
||||
return {
|
||||
isMoving,
|
||||
onMouseDown,
|
||||
onMouseMove,
|
||||
onMouseUp,
|
||||
onWheel
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user