@rc-component/color-picker
Version:
React Color Picker
102 lines (100 loc) • 3.28 kB
JavaScript
import { useEffect, useRef, useState } from 'react';
function getPosition(e) {
const obj = 'touches' in e ? e.touches[0] : e;
const scrollXOffset = document.documentElement.scrollLeft || document.body.scrollLeft || window.pageXOffset;
const scrollYOffset = document.documentElement.scrollTop || document.body.scrollTop || window.pageYOffset;
return {
pageX: obj.pageX - scrollXOffset,
pageY: obj.pageY - scrollYOffset
};
}
function useColorDrag(props) {
const {
targetRef,
containerRef,
direction,
onDragChange,
onDragChangeComplete,
calculate,
color,
disabledDrag
} = props;
const [offsetValue, setOffsetValue] = useState({
x: 0,
y: 0
});
const mouseMoveRef = useRef(null);
const mouseUpRef = useRef(null);
// Always get position from `color`
useEffect(() => {
setOffsetValue(calculate());
}, [color]);
useEffect(() => () => {
document.removeEventListener('mousemove', mouseMoveRef.current);
document.removeEventListener('mouseup', mouseUpRef.current);
document.removeEventListener('touchmove', mouseMoveRef.current);
document.removeEventListener('touchend', mouseUpRef.current);
mouseMoveRef.current = null;
mouseUpRef.current = null;
}, []);
const updateOffset = e => {
const {
pageX,
pageY
} = getPosition(e);
const {
x: rectX,
y: rectY,
width,
height
} = containerRef.current.getBoundingClientRect();
const {
width: targetWidth,
height: targetHeight
} = targetRef.current.getBoundingClientRect();
const centerOffsetX = targetWidth / 2;
const centerOffsetY = targetHeight / 2;
const offsetX = Math.max(0, Math.min(pageX - rectX, width)) - centerOffsetX;
const offsetY = Math.max(0, Math.min(pageY - rectY, height)) - centerOffsetY;
const calcOffset = {
x: offsetX,
y: direction === 'x' ? offsetValue.y : offsetY
};
// Exclusion of boundary cases
if (targetWidth === 0 && targetHeight === 0 || targetWidth !== targetHeight) {
return false;
}
onDragChange?.(calcOffset);
};
const onDragMove = e => {
e.preventDefault();
updateOffset(e);
};
const onDragStop = e => {
e.preventDefault();
document.removeEventListener('mousemove', mouseMoveRef.current);
document.removeEventListener('mouseup', mouseUpRef.current);
document.removeEventListener('touchmove', mouseMoveRef.current);
document.removeEventListener('touchend', mouseUpRef.current);
mouseMoveRef.current = null;
mouseUpRef.current = null;
onDragChangeComplete?.();
};
const onDragStart = e => {
// https://github.com/ant-design/ant-design/issues/43529
document.removeEventListener('mousemove', mouseMoveRef.current);
document.removeEventListener('mouseup', mouseUpRef.current);
if (disabledDrag) {
return;
}
updateOffset(e);
document.addEventListener('mousemove', onDragMove);
document.addEventListener('mouseup', onDragStop);
document.addEventListener('touchmove', onDragMove);
document.addEventListener('touchend', onDragStop);
mouseMoveRef.current = onDragMove;
mouseUpRef.current = onDragStop;
};
return [offsetValue, onDragStart];
}
export default useColorDrag;