reat scroll full page

全屏幕滚动

同事A:全屏幕滚动很难吗?不是有手就行?
对于这个问题,我有些不知如何回答。
我纯纯的认为 fullPage.js 月收一万五千美元的JavaScript组件不是没有原因的。
大概是大数据先前没见过搜索过全屏滚动组件库,搜索到的都不好用。无奈之下我就纯手写了一下。

纯手写历程:

  1. 先写一个节流,避免滑动距离过多,屏幕乱串。

节流:n秒内,频繁触发,只有第一次执行

  const throttle = useCallback(function (func: any, delay: number) {
    let timer: any = null;
    return function (this: any, ...args: any[]) {
      if (!timer) {
        timer = setTimeout(() => {
          func.apply(this, args);
          timer = null;
        }, delay);
      }
    };
  }, []);
  1. 滚轮向上滚/向下滚的时候改变页码
//全局变量
let currentPage = 1;
let scrolling = false;

function scrollUp(){
//你的函数体
}

function scrollDown(){
//我的部分函数体

if(scrolling) return;
//获取父容器
const wrapper: any = wrapperRef?.current;
wrapper.style.transition = `all 800ms cubic-bezier(.34,.86,.71,.95) 0s`;
  if (currentPage === 1) {
        wrapper.style.transform = `translate3d(0px, -${height}px, 0px)`;
        setTimeout(() => {
          currentPage = 2;
          scrolling = false;
        }, 800);
        return;
      }

      if (currentPage === 2) {
        wrapper.style.transform = `translate3d(0px, -${2 * height}px, 0px)`;
        setTimeout(() => {
        currentPage = 3;
        scrolling = false;
        }, 800);
        return;
      }
}
  1. pc端监听滚轮的动向
function scrollFunc(e: any) {
      let el = e || window.event;
      el.stopPropagation();
      if (el.wheelDelta) {
        if (el.wheelDelta > 0) {
          //当鼠标滚轮向上滚动时
         throttle(scrollUp(), 300);
        }
        if (el.wheelDelta < 0) {
          //当鼠标滚轮向下滚动时
          throttle(scrollDown(), 300);
        }
      } else if (e.detail) {
        if (el.detail < 0) {
          //当鼠标滚轮向上滚动时
          throttle(scrollUp(), 300);
        }
        if (el.detail > 0) {
          //当鼠标滚轮向下滚动时
          throttle(scrollDown(), 300);
        }
      }
    }
    // 给页面绑定鼠标滚轮事件,针对火狐的非标准事件
    window.addEventListener("DOMMouseScroll", scrollFunc); // 给页面绑定鼠标滚轮事件,针对Google,mousewheel非标准事件已被弃用,请使用 wheel事件代替
    window.addEventListener("wheel", scrollFunc); // ie不支持wheel事件,若一定要兼容,可使用mousewheel
    window.addEventListener("mousewheel", scrollFunc);
    let startY = 0; // 触摸起始位置的 y 坐标
    let endY = 0; // 触摸结束位置的 y 坐标

    // 监听 touchstart 事件
    document.addEventListener("touchstart", function (e) {
      startY = e.touches[0].pageY;
    });

    // 监听 touchend 事件
    document.addEventListener("touchend", function (e) {
      endY = e.changedTouches[0].pageY;
      const deltaY = endY - startY; // 计算 y 坐标的差值
      if (deltaY > 0) {
        throttle(scrollUp(), 300);
      } else if (deltaY < 0) {
        throttle(scrollDown(), 300);
      }
    });

总结:感觉没什么问题,但是page 和节流,和时间 的问题一直有偏差。

你会发现其实稍微滚一下鼠标滚轮mousewheel事件实际上会触发N多次。所以添加了节流并设一个setTimeout来让用户感觉"只是滚了-次滚轮"时mousewheel事件只触发一次,否则就会发生"好像我只滚了一下,但是页面却一连跳了好几页"的现象。
但是,笔记本的触摸板上有一个诡异的现象,似乎系统为了实现平滑滚动的效果还是其他原因(未考证),当你手指离开触摸板后mouserwheel依然还会执行一段时间,而且这段时间甚至会持续1-2秒,所以就会造成"貌似我只滚了一次,但是页面却跳了好几页"。同样的道理,假如你的手指一直在滚动,或者说PC上的滚轮一直在滚动(这个貌似比较难,鼠标的滚轮形状貌似决定了你不能一直拨动很久),当持续的时间超过这个setTimeout之后,就会触发第2次甚至第
3次mousewheel事件,页面就会跳。
解决的办法:
1.加大这个setTimeout的值。
2.加入一个控制变量scrolling,当开始滚动滚轮后scrolling=true.
将当每一屏的动画执行完毕后,这个信号量才置为false,这样就能极大减少用户误操作的次数了原理都是让一段时间内,mousewheel不能执行太多次。
但缺点是也可能会让某些用户觉得够不流畅

另外,手机端高度还不等于100vh哦!。

我是个追究细节的人。很多细节我处于无奈的地步。好吧!我承认自己平庸。
这种造轮子的事情还是留给大佬们吧!我还是适合站在巨人的肩膀上享受成果~

@fullpage/react-fullpage

npm i @fullpage/react-fullpage
安装和使用 @fullpage/react-fullpage 时遇到的疑难杂症
  • Failed to parse source map from xxxx file

You can remove the warning by adding GENERATE_SOURCEMAP=false to your .env file

  • TypeError: Cannot read property ‘destroy’ of undefined
    在这里插入图片描述

意思就是说,ReactFullpage.Wrapper 的子元素必须有一个类名为section的元素。
是啊!我有。但是我是xxx.module.scss 写法。它检测不到

错误写法:也是我的写法-_-!!!

  <ReactFullpage.Wrapper>
       <div className={styles.section}>第一个页面</div>
       <div className={styles.section}>第二个页面</div>
       <div className={styles.section}>第三个页面</div>
       <div className={styles.section}>第四个页面</div>
 </ReactFullpage.Wrapper>

正确写法:

import ReactFullpage from "@fullpage/react-fullpage";
import { useKeyPress, useSize } from "ahooks";
import "./demo.css";

export function Demo() {
   const size = useSize(document.querySelector("body"));
  const [page, setPage] = useState(0);
  const FullpageRef = useRef<any>(null);
  
  useKeyPress("uparrow", () => {
   //onKeyup();
   // 如果.section 页面中有input输入框的话,在手机浏览器调起软键盘,键盘收起来时会导致height的时间差,导致页面乱串
   // 哈哈哈,在移动端我就不调用向上的箭头 和 向下的箭头事件了
    if (size) {
      if (size?.width > 768) {
        onKeyup();
      }
    }
  });
  useKeyPress("downarrow", () => {
   // 如果.section 页面中有input输入框的话,在手机浏览器调起软键盘,键盘收起来时会导致height的时间差,导致页面乱串
   // 哈哈哈,在移动端我就不调用向上的箭头 和 向下的箭头事件了
    if (size) {
      if (size?.width > 768) {
        onKeydown();
      }
    }
   //onKeydown();
  });
  useKeyPress("enter", () => {
	onKeydown();
  });

  function onKeydown() {
    if (nextRef) {
      FullpageRef.current.moveSectionDown();
    }
  }

  function onKeyup() {
    if (nextRef) {
      FullpageRef.current.moveSectionUp();
    }
  }


  return (
    <div>
      <ReactFullpage
        //上面的参数设置都写在这里,不用再写在构造函数里面
        credits={{}}
        // navigation={true}
        scrollingSpeed={1000}
        scrollOverflow={true}
        scrollBar={true}
           onLeave={(origin, destination) => {
            setPage(destination.index);
          }}
       // afterLoad={(origin, destination) => {
       //   setPage(destination.index);
       // }}
        render={({ fullpageApi }) => {
             if (fullpageApi) {
              FullpageRef.current = fullpageApi;
            }
          return (
            <ReactFullpage.Wrapper>
              <div className="section">第一个页面</div>
              <div className="section">第二个页面</div>
              <div className="section">第三个页面</div>
              <div className="section">第四个页面</div>
            </ReactFullpage.Wrapper>
          );
        }}
      />
    </div>
  );
}

  • 如何解决fullpage.js使用中滑轮上下滚动过快导致屏幕乱窜的问题?

fullpage可以通过设背参数来调节治轮的灵敏度,从而能决屏慕乱蜜的问题。
具体来说、在fullpage配置项中设置scrolOverlow:tue、同时设置scrolBartruescroingSpeed: 1000、可以让滑轮滚动的速度变慢、并添加滚动条,更好地控制页面内容的滚动。此外,可以在.section 的css样式中添加overflow: hidden和height:100%来避免.section页面出现垂直滚动条。

  • Remove “Made with Fullpage.js” from website
    在这里插入图片描述
  • fullpage.js的licenseKey不填写licenseKey,会涉及到侵权问题吗?

呃!我想是会的。知识付费无可厚非,何况他免费提供了3年多
我们来看作者 Alvaro Trigo 的表述

因为我的产品是一个开源的 Javascript 组件,我遇到的最大问题就是不得不与开发人员"争吵",他们认为每个客户端产品都应该对所有人免费。这就是为什么当我开始销售扩展时,我必须明确表示它们不是开源的。

生而为人,我还是有点自觉性的。于是我在npm上挖呀挖!

react-page-scroller

import ReactPageScroller from "react-page-scroller";
import { useKeyPress, useSize } from "ahooks";

  const [page, setPage] = useState(0);
  const size = useSize(document.querySelector("body"));

  useKeyPress("uparrow", () => {
    //onKeyup();
    // 如果.section 页面中有input输入框的话,在手机浏览器调起软键盘,键盘收起来时会导致height的时间差,导致页面乱串
   // 哈哈哈,在移动端我就不调用向上的箭头 和 向下的箭头事件了
    if (size) {
      if (size?.width > 768) {
        onKeyup();
      }
    }
  });
  useKeyPress("downarrow", () => {
    //onKeydown();
   // 如果.section 页面中有input输入框的话,在手机浏览器调起软键盘,键盘收起来时会导致height的时间差,导致页面乱串
   // 哈哈哈,在移动端我就不调用向上的箭头 和 向下的箭头事件了
    if (size) {
      if (size?.width > 768) {
        onKeydown();
      }
    }
  });
  useKeyPress("enter", () => {
    onKeydown();
  });

  function onKeydown() {
    setPage((x) => {
      if (x === 12) {
        return 12;
      }
      return x + 1;
    });
  }

  function onKeyup() {
    setPage((x) => {
      if (x === 0) {
        return 0;
      }
      return x - 1;
    });
  }
  <ReactPageScroller
          pageOnChange={(page: number) => {
            setPage(page);
          }}
          customPageNumber={page}
        >
           <div className="section">第一个页面</div>
           <div className="section">第二个页面</div>
           <div className="section">第三个页面</div>
           <div className="section">第四个页面</div>
 </ReactPageScroller>

非常棒!移动端的height!==100vh 它都处理了。给我省了不少麻烦

如果你有更好使的库也可以分享给我呀!让我们一起少走弯路!

  • 30
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
react-scroll是一个用于实现平滑滚动效果的React软件包。它提供了一种简单的方式来将滚动动画应用于React应用程序中的元素。通过使用react-scroll,您可以轻松地将页面滚动到指定的位置或元素。 以下是一个使用react-scroll实现滚动到指定元素的示例: ```jsx import React from "react"; import { Link, animateScroll as scroll } from "react-scroll"; const App = () => { const scrollToTop = () => { scroll.scrollToTop(); }; const scrollToElement = () => { scroll.scrollTo(500); // 滚动到页面上距离顶部500像素的位置 }; return ( <div> <Link activeClass="active" to="element" spy={true} smooth={true} offset={-70} duration={500} > Scroll to Element </Link> <div id="element" style={{ height: "1000px" }}> Scroll to this Element </div> <button onClick={scrollToTop}>Scroll to Top</button> <button onClick={scrollToElement}>Scroll to Element</button> </div> ); }; export default App; ``` 在上面的示例中,我们首先导入了`Link`和`animateScroll`组件。然后,我们在组件中定义了两个滚动函数`scrollToTop`和`scrollToElement`。`scrollToTop`函数将页面滚动到顶部,而`scrollToElement`函数将页面滚动到距离顶部500像素的位置。 在组件的返回部分,我们使用`Link`组件创建了一个链接,当点击该链接时,页面将平滑滚动到具有id为"element"的元素。我们还在`Link`组件中设置了一些属性,例如`spy`用于监听滚动事件,`smooth`用于实现平滑滚动效果,`offset`用于设置滚动位置的偏移量,`duration`用于设置滚动动画的持续时间。 最后,我们在页面上创建了一个具有id为"element"的元素,以便我们可以滚动到该元素。我们还创建了两个按钮,分别用于触发`scrollToTop`和`scrollToElement`函数。 这样,当您点击"Scroll to Element"链接或按钮时,页面将平滑滚动到具有id为"element"的元素。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值