Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC] useIsScrolling #2461

Open
JacobZyy opened this issue Jan 31, 2024 · 3 comments · May be fixed by #2488
Open

[RFC] useIsScrolling #2461

JacobZyy opened this issue Jan 31, 2024 · 3 comments · May be fixed by #2488
Labels
feature New feature or request v4

Comments

@JacobZyy
Copy link

用于获取页面或者页面中某个元素是否正在滚动

使用场景

某些场景下需要响应目标元素的滚动状态

例如:目标元素滚动时需要收起某个浮窗,滚动停止时又需要展示。

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>
    </>
  );
};

演示

20240131111416

@crazylxr
Copy link
Collaborator

合理,这个 hooks 可以加

@crazylxr crazylxr added feature New feature or request v4 labels Feb 26, 2024
@JacobZyy
Copy link
Author

合理,这个 hooks 可以加

好的大佬!那我整理整理提个pr?

@liuyib
Copy link
Collaborator

liuyib commented Feb 26, 2024

@JacobZyy 提吧,我们看见了就 review 了

@JacobZyy JacobZyy linked a pull request Feb 27, 2024 that will close this issue
18 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature New feature or request v4
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants