react 实现爬楼层效果

本文详细介绍了如何在React应用中实现基于页面滚动的动态顶部栏(appbar)效果。通过监听滚动事件,计算不同区块的位置,动态调整appbar的样式和隐藏状态,同时涉及到元素定位、粘性定位以及页面不同区域的交互处理。内容涵盖了状态管理、性能优化(节流函数)和DOM操作等关键点。
摘要由CSDN通过智能技术生成
<!-- 我原有的Home3.0逻辑 爬楼层效果 -->

  const [blockTop, setBlockTop] = useState<{ top: number; bgMode: string }[]>(
    [],
  );

    const getBannerHeight = () => {
    const banner = document.getElementById('banner');
    const appbar = document.getElementById('appbar');
    if (banner && appbar) {
      const bannerTop = getElementTop(banner);
      const bannerHeight = banner.clientHeight;
      return bannerTop + bannerHeight - appbar.offsetHeight;
    }
    return 0;
  };

  // 只获取了首页 top和bg
  const getBlockTop = () => {
    const blockEle = document.getElementById('home_wrap')?.childNodes || [];
    return Array.from(blockEle)?.map(item => {
      const bgMode =
        window.getComputedStyle(item, null)?.backgroundColor ||
        item.currentStyle.background;
      const top = item.offsetTop;
      return { bgMode: bgMode.includes('255') ? 'light' : 'dark', top };
    });
  };

  // chang appbarState
  const changAppbarState = (blockTopList, top) => {
    for (let i = 0; i < blockTopList.length - 1; i++) {
      if (blockTopList[i].top <= top && top < blockTopList[i + 1].top) {
        if (blockTopList[i].bgMode === 'light') {
          setAppbarState('light');
        } else {
          setAppbarState('dark');
        }
      }
      if (top > blockTopList[blockTop.length - 1].top) {
        if (blockTopList[blockTop.length - 1].bgMode === 'light') {
          setAppbarState('light');
        } else {
          setAppbarState('dark');
        }
      }
    }
  };

  const scrollEventHome = throttle(() => {
    const top = getDocumentScrollTop();
    if (Object.keys(blockTop).length) {
      changAppbarState(blockTop, top);
    }
    // 粘性消失隐藏
    if (Anchor.isAffix()) {
      if (prevTop < 0) {
        !Anchor.stop && setHidden(true);
      }
      if (prevTop >= 0 && prevTop < top) {
        !Anchor.stop && setHidden(true);
      }
    }
    // 上滑下滑消失隐藏
    if (prevTop >= 0 && prevTop - top > 10) {
      !Anchor.stop && setHidden(false);
    }

    if (prevTop >= 0 && prevTop - top < -10) {
      !Anchor.stop && setHidden(true);
    }

    prevTop = top;
  }, 300);

  const scrollEventOther = throttle(() => {
    const top = getDocumentScrollTop();
    const banner = document.getElementById('banner');
    const bannerHeight = getBannerHeight();

    if (banner) {
      if (top > 0) {
        if (top > bannerHeight) {
          setAppbarState('light');
        } else {
          setAppbarState('dark');
        }
      } else {
        setAppbarState('dark');
      }
    }
    if (Anchor.isAffix()) {
      if (prevTop < 0) {
        !Anchor.stop && setHidden(true);
      }
      if (prevTop >= 0 && prevTop < top) {
        !Anchor.stop && setHidden(true);
      }
    }

    if (prevTop >= 0 && prevTop > top) {
      !Anchor.stop && setHidden(false);
    }

    prevTop = top;
  }, 200);

   useEffect(() => {
     if (pathName === '/' && !Object.keys(blockTop).length) {
       setBlockTop(getBlockTop());
       return;
     } else if (pathName === '/' && Object.keys(blockTop).length) {
       APP_BAR_SCROLL_EVENT = scrollEventHome;
     } else {
       APP_BAR_SCROLL_EVENT = scrollEventOther;
     }

     canUseDom && window.addEventListener('scroll', APP_BAR_SCROLL_EVENT, false);
     setTimeout(() => {
       APP_BAR_SCROLL_EVENT();
     }, 0);

     setTimeout(() => {
       if (document.documentElement.scrollTop !== 0) {
         scrollTo(Math.max(0, document.documentElement.scrollTop + 1));
       }
     }, 10);

     // eslint-disable-next-line consistent-return
     return function clearUp() {
       canUseDom && window.removeEventListener('scroll', APP_BAR_SCROLL_EVENT);
     };
   }, [blockTop]);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值