improve timeline scrolling with dynamic speed (#10677)

This commit is contained in:
Josh Hawkins 2024-03-25 21:29:42 -05:00 committed by GitHub
parent 30d93e1d90
commit bc6b4c38b8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -42,6 +42,7 @@ function useDraggableElement({
}: DraggableElementProps) { }: DraggableElementProps) {
const [clientYPosition, setClientYPosition] = useState<number | null>(null); const [clientYPosition, setClientYPosition] = useState<number | null>(null);
const [initialClickAdjustment, setInitialClickAdjustment] = useState(0); const [initialClickAdjustment, setInitialClickAdjustment] = useState(0);
const [scrollEdgeSize, setScrollEdgeSize] = useState<number>();
const [segments, setSegments] = useState<HTMLDivElement[]>([]); const [segments, setSegments] = useState<HTMLDivElement[]>([]);
const { alignStartDateToTimeline, getCumulativeScrollTop } = useTimelineUtils( const { alignStartDateToTimeline, getCumulativeScrollTop } = useTimelineUtils(
{ {
@ -52,23 +53,24 @@ function useDraggableElement({
); );
const draggingAtTopEdge = useMemo(() => { const draggingAtTopEdge = useMemo(() => {
if (clientYPosition && timelineRef.current) { if (clientYPosition && timelineRef.current && scrollEdgeSize) {
return ( return (
clientYPosition - timelineRef.current.offsetTop < clientYPosition - timelineRef.current.offsetTop < scrollEdgeSize &&
timelineRef.current.clientHeight * 0.03 && isDragging isDragging
); );
} }
}, [clientYPosition, timelineRef, isDragging]); }, [clientYPosition, timelineRef, isDragging, scrollEdgeSize]);
const draggingAtBottomEdge = useMemo(() => { const draggingAtBottomEdge = useMemo(() => {
if (clientYPosition && timelineRef.current) { if (clientYPosition && timelineRef.current && scrollEdgeSize) {
return ( return (
clientYPosition > clientYPosition >
(timelineRef.current.clientHeight + timelineRef.current.offsetTop) * timelineRef.current.clientHeight +
0.97 && isDragging timelineRef.current.offsetTop -
scrollEdgeSize && isDragging
); );
} }
}, [clientYPosition, timelineRef, isDragging]); }, [clientYPosition, timelineRef, isDragging, scrollEdgeSize]);
const getClientYPosition = useCallback( const getClientYPosition = useCallback(
(e: MouseEvent | TouchEvent) => { (e: MouseEvent | TouchEvent) => {
@ -290,17 +292,26 @@ function useDraggableElement({
} }
}); });
if (draggingAtTopEdge || draggingAtBottomEdge) { if ((draggingAtTopEdge || draggingAtBottomEdge) && scrollEdgeSize) {
let newPosition = clientYPosition;
if (draggingAtTopEdge) { if (draggingAtTopEdge) {
newPosition = scrolled - segmentHeight; const intensity = Math.max(
timelineRef.current.scrollTop = newPosition; 0,
(scrollEdgeSize - (clientYPosition - timelineTopAbsolute)) /
scrollEdgeSize,
);
timelineRef.current.scrollTop -= segmentHeight * intensity;
} }
if (draggingAtBottomEdge) { if (draggingAtBottomEdge) {
newPosition = scrolled + segmentHeight; const intensity = Math.max(
timelineRef.current.scrollTop = newPosition; 0,
(clientYPosition -
timelineTopAbsolute -
(timelineRef.current.getBoundingClientRect().height -
scrollEdgeSize)) /
scrollEdgeSize,
);
timelineRef.current.scrollTop += segmentHeight * intensity;
} }
} }
@ -436,6 +447,12 @@ function useDraggableElement({
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [timelineCollapsed]); }, [timelineCollapsed]);
useEffect(() => {
if (timelineRef.current) {
setScrollEdgeSize(timelineRef.current.clientHeight * 0.03);
}
}, [timelineRef]);
return { handleMouseDown, handleMouseUp, handleMouseMove }; return { handleMouseDown, handleMouseUp, handleMouseMove };
} }