JS实现滚动条平滑滚动到顶部的方式

1,922 阅读2分钟

【前言】

顺滑的意思是值动画帧数在60帧以上,也就是动画变化的时间间隔在16.6ms以下就可以到达顺滑的效果。由于setTimeout受影响的因素太多,所以平常顺滑版用requestAnimationFrame来实现。


<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        body,
        html {
            height: 350%;
            width: 350%;
        }
        
        div {
            /* margin-left: 10px; */
        }
        
        #div1 {
            width: 100px;
            height: 100px;
            background-color: yellow;
            position: absolute;
            top: 100px;
        }
        
        #div2 {
            width: 100px;
            height: 100px;
            background-color: lightblue;
            position: absolute;
            top: 250px;
        }
        
        #div3 {
            width: 100px;
            height: 100px;
            background-color: grey;
            position: absolute;
            top: 400px;
        }
        
        #btn1 {
            position: fixed;
            right: 50px;
            bottom: 100px;
            display: inline-block;
            width: 100px;
            height: 50px;
        }
    </style>
</head>

<body>
    <div id="div1"></div>
    <div id="div2"></div>
    <div id="div3"></div>
    <button id="btn1">top</button>
    <style>

    </style>
    <script>
        /**
         * 经测试,requestAnimationFrame会同步页面所有的动画函数的执行频率(渲染的时刻还是按照原先的函数执行时间来,只不过函数已经按照变化后的频率在后台执行了)
         * 
         * 
         * 
         * 
         * 
         */
        function rowMove() { //左右元素的移动比较(非时间版)
            let _right;
            let start1 = true;
            let startTime1 = 0;
            let end1 = 0;
            let start2 = true;
            let startTime2 = 0;
            let end2 = 0;

            function moveDiv1(distance = 10) {
                if (start1) {
                    startTime1 = Date.now();
                    start1 = false;
                }
                let ele = document.querySelector('#div1');
                let masDistance = document.body.clientWidth;
                let eleWidth = ele.offsetWidth; //元素总宽
                _right = _right ? _right : masDistance - eleWidth;
                if (_right > distance) {
                    _right = _right - distance;
                    ele.style.right = _right + 'px';
                } else {
                    end1 = Date.now();
                    ele.style.right = 0;
                    console.log(end1 - startTime1)
                    throw 'settimeout'
                }

            }

            function moveDiv2(distance = 10) {
                if (start2) {
                    startTime2 = Date.now();
                    start2 = false;
                }
                let ele = document.querySelector('#div2');
                let masDistance = document.body.clientWidth;
                let eleWidth = ele.offsetWidth; //元素总宽
                _right = _right ? _right : masDistance - eleWidth;

                if (_right > distance) {
                    _right = _right - distance;
                    ele.style.right = _right + 'px';
                } else {
                    end2 = Date.now();
                    ele.style.right = 0;
                    console.log(end2 - startTime2)

                    throw 'requestAnimationFrame'
                }

            }

            function setTimeoutMove() { //非平滑移动
                moveDiv1();
                console.log('setTimeoutMove')
                setTimeout(setTimeoutMove, 0);
            }


            function requerFrameAnimationMove() { //平滑移动
                moveDiv2()
                console.log('requerFrameAnimationMove')
                requestAnimationFrame(requerFrameAnimationMove)
            }
            // setTimeoutMove();
            requerFrameAnimationMove();
        }




        function scrollMove() { // 平滑移动时间版
            let top;
            let speed;
            let startTime = Date.now();
            top = document.body.scrollTop || document.documentElement.scrollTop || window.pageYOffset;

            function move(distance = 10, time = 1000) {
                speed = (top / time);
                distance = speed * (Date.now() - startTime);
                top = top - distance;
                document.documentElement.scrollTop = top;
                if (top <= 0) {
                    throw 123
                }
            }

            function stMove() {
                try {
                    move();
                    setTimeout(stMove, 16.6)
                } catch (e) {
                    return
                }
            }

            function raf() {
                try {
                    move();
                    requestAnimationFrame(raf)
                } catch (e) {
                    return
                }
            }
            // stMove()
            raf()
        }
        // rowMove()
        document.querySelector("#btn1").addEventListener('click', scrollMove, false)
    </script>
</body>

</html>