• 点击滚动到任意位置


    滚动到任意位置

    涉及知识点:

    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)
            }
        })
    }
    
  • 相关阅读:
    0593. Valid Square (M)
    0832. Flipping an Image (E)
    1026. Maximum Difference Between Node and Ancestor (M)
    0563. Binary Tree Tilt (E)
    0445. Add Two Numbers II (M)
    1283. Find the Smallest Divisor Given a Threshold (M)
    C Primer Plus note9
    C Primer Plus note8
    C Primer Plus note7
    C Primer Plus note6
  • 原文地址:https://www.cnblogs.com/MrZhujl/p/14570227.html
Copyright © 2020-2023  润新知