Open
Description
用于获取页面或者页面中某个元素是否正在滚动
使用场景
某些场景下需要响应目标元素的滚动状态
例如:目标元素滚动时需要收起某个浮窗,滚动停止时又需要展示。
API
export type Target = BasicTarget<Element | Document>;
export type Options = {
target?: Target;
/** @default 'vertical' */
scrollDirection?: 'vertical' | 'horizontal';
};
type Position = { left: number; top: number };
const getCurrentScrollPosition = (scrollEl: Target): Position => {
if (!scrollEl) return { left: 0, top: 0 };
let newPosition: Position;
if (scrollEl === document) {
if (document.scrollingElement) {
newPosition = {
left: document.scrollingElement.scrollLeft,
top: document.scrollingElement.scrollTop,
};
} else {
newPosition = {
left: Math.max(
window.pageXOffset,
document.documentElement.scrollLeft,
document.body.scrollLeft,
),
top: Math.max(
window.pageYOffset,
document.documentElement.scrollTop,
document.body.scrollTop,
),
};
}
} else {
newPosition = {
left: (scrollEl as Element).scrollLeft,
top: (scrollEl as Element).scrollTop,
};
}
return newPosition;
};
const useIsScrolling = (option?: Options): boolean => {
const { scrollDirection = 'vertical', target } = option ?? {};
const [isScrolling, setIsScrolling] = useState<boolean>(false);
const prevPosition = useRef<Position | undefined>();
const latestScrolling = useLatest(isScrolling);
useEffectWithTarget(
() => {
const scrollEl = getTargetElement(target, document);
if (!scrollEl) return;
const getIsScrolling = () => {
const newPosition = getCurrentScrollPosition(scrollEl);
if (!prevPosition.current) {
prevPosition.current = newPosition;
return;
}
const delay = latestScrolling.current ? 500 : 100;
setRafTimeout(() => {
if (scrollDirection === 'vertical') {
setIsScrolling(prevPosition.current?.top !== newPosition.top);
} else if (scrollDirection === 'horizontal') {
setIsScrolling(prevPosition.current?.left !== newPosition.left);
}
}, delay);
prevPosition.current.top = newPosition.top;
prevPosition.current.left = newPosition.left;
};
getIsScrolling();
scrollEl.addEventListener('scroll', getIsScrolling);
return () => {
scrollEl.removeEventListener('scroll', getIsScrolling);
};
},
[],
target,
);
return isScrolling;
};
export default useIsScrolling;
demo
import React, { useRef } from 'react';
import { useIsScrolling } from 'ahooks';
export default () => {
const ref = useRef(null);
const scroll = useIsScrolling({ target: ref });
return (
<>
<p>{JSON.stringify(scroll)}</p>
<div
style={{
height: '160px',
width: '160px',
border: 'solid 1px #000',
overflow: 'scroll',
whiteSpace: 'nowrap',
fontSize: '32px',
}}
ref={ref}
>
<div>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. A aspernatur atque, debitis ex
excepturi explicabo iste iure labore molestiae neque optio perspiciatis
</div>
<div>
Aspernatur cupiditate, deleniti id incidunt mollitia omnis! A aspernatur assumenda
consequuntur culpa cumque dignissimos enim eos, et fugit natus nemo nesciunt
</div>
<div>
Alias aut deserunt expedita, inventore maiores minima officia porro rem. Accusamus ducimus
magni modi mollitia nihil nisi provident
</div>
<div>
Alias aut autem consequuntur doloremque esse facilis id molestiae neque officia placeat,
quia quisquam repellendus reprehenderit.
</div>
<div>
Adipisci blanditiis facere nam perspiciatis sit soluta ullam! Architecto aut blanditiis,
consectetur corporis cum deserunt distinctio dolore eius est exercitationem
</div>
<div>Ab aliquid asperiores assumenda corporis cumque dolorum expedita</div>
<div>
Culpa cumque eveniet natus totam! Adipisci, animi at commodi delectus distinctio dolore
earum, eum expedita facilis
</div>
<div>
Quod sit, temporibus! Amet animi fugit officiis perspiciatis, quis unde. Cumque
dignissimos distinctio, dolor eaque est fugit nisi non pariatur porro possimus, quas quasi
</div>
<div>
Quod sit, temporibus! Amet animi fugit officiis perspiciatis, quis unde. Cumque
dignissimos distinctio, dolor eaque est fugit nisi non pariatur porro possimus, quas quasi
</div>
<div>
Quod sit, temporibus! Amet animi fugit officiis perspiciatis, quis unde. Cumque
dignissimos distinctio, dolor eaque est fugit nisi non pariatur porro possimus, quas quasi
</div>
<div>
Quod sit, temporibus! Amet animi fugit officiis perspiciatis, quis unde. Cumque
dignissimos distinctio, dolor eaque est fugit nisi non pariatur porro possimus, quas quasi
</div>
<div>
Quod sit, temporibus! Amet animi fugit officiis perspiciatis, quis unde. Cumque
dignissimos distinctio, dolor eaque est fugit nisi non pariatur porro possimus, quas quasi
</div>
</div>
</>
);
};