• 点击滚动到任意位置


    滚动到任意位置

    涉及知识点:

    window.scrollTo(x, y)
    requestAnimationFrame(()=>{})  //帧动画,优点:按浏览器的刷新频率渲染,更加流畅。特点:类似 setTimeout 只执行一次
    

    原生的写法:

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
      <style>
        * {
          margin: 0;
          padding: 0;
          box-sizing: border-box;
        }
    
        main {
           100vw;
          height: 100vh;
          overflow: auto;
        }
    
        main>.content div {
          transition: all 1s ease-in-out;
          height: 200px;
          border: 1px solid #000;
        }
    
        #box1 {
          background-color: red;
        }
    
        #box2 {
          background-color: orange;
        }
    
        #box3 {
          background-color: yellow;
        }
    
        #box4 {
          background-color: green;
        }
    
        #box5 {
          background-color: cyan;
        }
    
        #box6 {
          background-color: blue;
        }
    
        #box7 {
          background-color: blueviolet;
        }
    
        #but {
          outline: none;
          position: fixed;
          bottom: 30px;
          right: 30px;
          display: inline-block;
           70px;
          height: 70px;
          line-height: 70px;
          border-radius: 50%;
          border: 1px solid red;
          font-size: 12px;
          text-align: center;
          z-index: 1000;
        }
      </style>
    </head>
    
    <body>
      <main>
        <button href="javascript:;" id="but">回到box2</button>
        <div class="content">
          <div id="box1">1</div>
          <div id="box2">2</div>
          <div id="box3">3</div>
          <div id="box4">4</div>
          <div id="box5">5</div>
          <div id="box6">6</div>
          <div id="box7">7</div>
        </div>
      </main>
      <script>
        const but = document.getElementById("but");
        but.onclick = () => {
          const main = document.querySelector("main"); // 获取滚动的元素(带滚动条)
          const toTop = document.getElementById("box2").offsetTop; // 获取需要滚动的高度
          smoothscroll(main, toTop)
        };
        // smoothscroll(需要滚动的元素(默认document), 滚动的最终高度(默认0), 速度(默认1.4))
        const smoothscroll = (ele, toTop = 0, speed = 1.4) => {
          if (!ele) {
            ele = document.documentElement || document.body;
          }
          if (speed <= 1) {
            speed = 1.4
          }
          let timer = null;
          let scrollTo = () => {
            const Dvalue = ele.scrollTop - toTop; // 到目标点的距离,正数:需要向上滚,负数:需要向下滚
            const absDvalue = Math.abs(Dvalue); // 和目标点的距离
            const distance = absDvalue - (absDvalue / speed); // 需要滚动的距离
            const onOff = distance < 1; // 判断是否已到位,距离小于1px是,表示已到位
            if (Dvalue > 0 && !onOff) { // 向上滚
              ele.scrollTop = ele.scrollTop - distance;
              timer = window.requestAnimationFrame(scrollTo);
            }
            if (Dvalue < 0 && !onOff) { // 向下滚
              ele.scrollTop = ele.scrollTop + distance;
              timer = window.requestAnimationFrame(scrollTo);
            }
            if (onOff) {
              console.log("滚到了")
              ele.scrollTop = toTop;
              window.cancelAnimationFrame(timer);
            };
          };
          scrollTo();
        };
      </script>
    </body>
    
    </html>
    

    react 版代码:

      num 是需要到达的位置, 数字类型。调用:this.transitionScroll(100)
      下面这段代码,只需要知道,每个索引对应的高度就可以了。

    let timer = null;
    
    this.state = {
        onOff: true, //初始值为true,默认可以点击,在滚动的时候变成false,结束滚动再次为true
        active: 0
    }
    
    headerBtnClick = (index) => { //点击改变索引
        if(this.state.onOff) {
            this.setState({
                active: index
            }, () => {
                this.scrollFn(index)
            })
        }
    }
    
    scrollFn = (index) => {  //每个索引对应的位置
        //this.transitionScroll(...)  根据索引,判断需要滚动到的位置。
    }
    
    componentDidMount() {
        window.addEventListener("scroll", () => { //监听是否为滚动状态,在滚动状态不可再次点击
            clearTimeout(timer) //利用防抖技巧,在结束滚动250ms之后恢复可点击状态
            timer = setTimeout(() => {
                this.setState({
                    onOff: true
                })
            }, 250)
            this.setState({
                onOff: false
            })
        })
    }
    
    componentWillUnmount() {
        if(timer) {
            clearTimeout(timer)
        }
    }
    //sensitivity: 容错率和灵敏度为 5 时正好
    //容错率越小,滚动的位置越精确,太小可能会出现无限回调的错误(主要原因是数字相除再取整,值不再精确)
    transitionScroll = (num) => { //判断需要上滚,还是下滚
        const n = window.pageYOffset;
        if(num < n) {
            this.ScrollDown(num)
        }
        if(num > n) {
            this.ScrollUp(num)
        }
    }
    
    ScrollDown = (num) => {  //向下滚
        const sensitivity = 5;
        window.requestAnimationFrame(() => {
            const n = window.pageYOffset;
            const Dvalue = Math.abs(num - n);
            if (num > n + sensitivity) {//容错率
                window.scrollTo(0, n + parseInt(Dvalue / sensitivity))//灵敏度
                this.ScrollDown(num)
            }
        })
    }
       
    ScrollUp = (num) => {  //向上滚
        const sensitivity = 5;
        window.requestAnimationFrame(() => {
            const n = window.pageYOffset;
            const Dvalue = Math.abs(num - n);
            if (num < n - sensitivity) {
                window.scrollTo(0, n - parseInt(Dvalue / sensitivity))
                this.ScrollDown(num)
            }
        })
    }
    
  • 相关阅读:
    [51nod1247]可能的路径(思维题)
    天梯赛L1020 帅到没朋友(map的使用)(模拟,数组非排序去重)
    洛谷 p1030 树的遍历
    天梯赛L1046 整除光棍(模拟)
    牛客,并查集,简单dp经商
    天梯赛L1043 阅览室 模拟题
    天梯赛L1049(模拟+vector的使用)
    天梯赛L1011,简单模拟
    codeforces 1201 c
    天梯赛L2003月饼(简单排序题)
  • 原文地址:https://www.cnblogs.com/MrZhujl/p/14570227.html
Copyright © 2020-2023  润新知