Skip to content

Commit 2488bb6

Browse files
committed
feat: support mouse down scroll
1 parent 776411b commit 2488bb6

File tree

3 files changed

+86
-8
lines changed

3 files changed

+86
-8
lines changed

src/List.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { useGetSize } from './hooks/useGetSize';
1515
import useHeights from './hooks/useHeights';
1616
import useMobileTouchMove from './hooks/useMobileTouchMove';
1717
import useOriginScroll from './hooks/useOriginScroll';
18+
import useScrollDrag from './hooks/useScrollDrag';
1819
import type { ScrollPos, ScrollTarget } from './hooks/useScrollTo';
1920
import useScrollTo from './hooks/useScrollTo';
2021
import type { ExtraRenderInfo, GetKey, RenderFunc, SharedConfig } from './interface';
@@ -436,6 +437,11 @@ export function RawList<T>(props: ListProps<T>, ref: React.Ref<ListRef>) {
436437
return false;
437438
});
438439

440+
// MouseDown drag for scroll
441+
useScrollDrag(inVirtual, componentRef, (offset) => {
442+
syncScrollTop((top) => top + offset);
443+
});
444+
439445
useLayoutEffect(() => {
440446
// Firefox only
441447
function onMozMousePixelScroll(e: WheelEvent) {

src/ScrollBar.tsx

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import classNames from 'classnames';
22
import raf from 'rc-util/lib/raf';
33
import * as React from 'react';
4+
import { getPageXY } from './hooks/useScrollDrag';
45

56
export type ScrollBarDirectionType = 'ltr' | 'rtl';
67

@@ -23,14 +24,6 @@ export interface ScrollBarRef {
2324
delayHidden: () => void;
2425
}
2526

26-
function getPageXY(
27-
e: React.MouseEvent | React.TouchEvent | MouseEvent | TouchEvent,
28-
horizontal: boolean,
29-
) {
30-
const obj = 'touches' in e ? e.touches[0] : e;
31-
return obj[horizontal ? 'pageX' : 'pageY'];
32-
}
33-
3427
const ScrollBar = React.forwardRef<ScrollBarRef, ScrollBarProps>((props, ref) => {
3528
const {
3629
prefixCls,

src/hooks/useScrollDrag.ts

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import raf from 'rc-util/lib/raf';
2+
import * as React from 'react';
3+
4+
function smoothScrollOffset(offset: number) {
5+
return Math.floor(offset ** 0.5);
6+
}
7+
8+
export function getPageXY(
9+
e: React.MouseEvent | React.TouchEvent | MouseEvent | TouchEvent,
10+
horizontal: boolean,
11+
) {
12+
const obj = 'touches' in e ? e.touches[0] : e;
13+
return obj[horizontal ? 'pageX' : 'pageY'];
14+
}
15+
16+
export default function useScrollDrag(
17+
inVirtual: boolean,
18+
componentRef: React.RefObject<HTMLElement>,
19+
onScrollOffset: (offset: number) => void,
20+
) {
21+
React.useEffect(() => {
22+
const ele = componentRef.current;
23+
if (inVirtual && ele) {
24+
let mouseDownLock = false;
25+
let rafId: number;
26+
let offset: number;
27+
28+
const stopScroll = () => {
29+
raf.cancel(rafId);
30+
};
31+
32+
const continueScroll = () => {
33+
stopScroll();
34+
35+
rafId = raf(() => {
36+
onScrollOffset(offset);
37+
continueScroll();
38+
});
39+
};
40+
41+
const onMouseDown = () => {
42+
mouseDownLock = true;
43+
};
44+
const onMouseUp = () => {
45+
mouseDownLock = false;
46+
stopScroll();
47+
};
48+
const onMouseMove = (e: MouseEvent) => {
49+
if (mouseDownLock) {
50+
const mouseY = getPageXY(e, false);
51+
const { top, bottom } = ele.getBoundingClientRect();
52+
53+
if (mouseY <= top) {
54+
const diff = top - mouseY;
55+
offset = smoothScrollOffset(diff);
56+
continueScroll();
57+
} else if (mouseY >= bottom) {
58+
const diff = mouseY - bottom;
59+
offset = smoothScrollOffset(diff);
60+
continueScroll();
61+
} else {
62+
stopScroll();
63+
}
64+
}
65+
};
66+
67+
ele.addEventListener('mousedown', onMouseDown);
68+
ele.ownerDocument.addEventListener('mouseup', onMouseUp);
69+
ele.ownerDocument.addEventListener('mousemove', onMouseMove);
70+
71+
return () => {
72+
ele.removeEventListener('mousedown', onMouseDown);
73+
ele.ownerDocument.removeEventListener('mouseup', onMouseUp);
74+
ele.ownerDocument.removeEventListener('mousemove', onMouseMove);
75+
stopScroll();
76+
};
77+
}
78+
}, [inVirtual]);
79+
}

0 commit comments

Comments
 (0)