用hooks实现一个返回顶部,滚动粘连效果

225 阅读1分钟
前言

最近需求里会有返回顶部这样一个功能,然后会有一些判断逻辑在里面,以及加上了粘连的效果,可以在各种容器中完美适应。

效果

o22g0-zrnsc.gif

代码
import React, { useEffect, useState } from 'react';

import { ReactComponent as Svg } from 'assets/svgs/common/up.svg';

import classnames from './index.module.styl';

function TopAnchor() {
  const [hidden, setHidden] = useState(true);

  const getWindowSize = () => ({
    innerHeight: window.innerHeight,
    innerWidth: window.innerWidth
  });

  const [windowsSize, setWindowsSize] = useState(getWindowSize());
  const [scrollTop, setScrollTop] = useState(0);

  useEffect(() => {
    // 滚动高度超过1.5屏显示
    setHidden(scrollTop < 1.5 * windowsSize.innerHeight);
  }, [scrollTop, windowsSize, setHidden]);

  const handleResize = () => {
    setWindowsSize(getWindowSize());
  };

  const handleScroll = () => {
    const newScrollTop =
      document.documentElement.scrollTop || document.body.scrollTop;
    setScrollTop(newScrollTop);
  };

  useEffect(() => {
    // 监听
    window.addEventListener('resize', handleResize);
    // 销毁
    return () => window.removeEventListener('resize', handleResize);
  });

  useEffect(() => {
    // 监听
    window.addEventListener('scroll', handleScroll);
    // 销毁
    return () => window.removeEventListener('scroll', handleScroll);
  });

  const backToTop = () => {
    document.body.scrollTop = document.documentElement.scrollTop = 0;
  };

  return (
    <div
      className={
        classnames['top-anchor'] +
        ' ' +
        `${hidden ? classnames['top-anchor-hidden'] : ''}`
      }
      onClick={backToTop}
    >
      <Svg className={classnames['top-anchor-up']} />
    </div>
  );
}

export default TopAnchor;
.top-anchor {
  position: sticky;
  margin-top: -51px;
  left: calc(50% + 640px + 13px);
  bottom: 24px;
  width: 50px;
  height: 50px;
  border: 2px solid #0096FF;
  border-radius: 5px;
  cursor: pointer;
  display: flex;
  justify-content: center;
  align-items: center;

  &:hover {
    border: 2px solid #2B76FF;
  }

  &:active {
    border: 2px solid #265FC7;
  }
}

.top-anchor-hidden {
  display: none;
}

.top-anchor-up {
  width: 27px;
  height: 28px;
}

结束语

码字不易,觉得不错的还请点个赞,谢谢!