原生JS實現滾動條

原生JS模擬滾動條

  • 求滾動條的高度

  可視內容區的高度 / 內容區的實際高度 = 滾動條的高度 / 滑道的高度

  • 求內容區top的值

  內容區距離頂部的距離 / (內容區的實際高度 - 可視內容區域的高度 ) = 滾動條距離頂部的距離 / ( 滑道的高度 - 滾動條的高度)

  • 使用onmousewheel作好兼容處理

    document.onmousewheel = function (e){
        //    e.wheelDelta < 0 //(-120)  向下
        //    e.wheelDelta > 0 //(120)  向上
        }
    //兼容  Firefox 
    document.addEventListener('DOMMouseScroll',function (e) {
            // e.detail > 0  //(3)  滑輪向下滾動
            // e.detail < 0  //(-3)  滑輪向上滾動
        },false)
  • 滾動條的運動方向跟內容區的運動方向相反

    • 當滾輪向上運動時 --> 內容區向下運動

    • 當滾輪向下運動時 --> 內容區向上運動

  • 舉個例子

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>滾動條</title>
    <style>
    *{
        padding: 0;
        margin: 0;
    }
    html,body{
        width: 100%;
        height: 100%;
    }
    .wrapper{
        position: absolute;
        left: 50%;
        top:50%;
        transform: translate(-50%,-50%);
        width: 800px;
        height: 700px;
        border: 1px solid #000;
    }
    .view_box{
        position: absolute;
        left: 100px;
        top:50%;
        transform: translateY(-50%);
        width:600px;
        height: 500px;
        background-color: rgba(25, 25, 25,.7);
        overflow: hidden;
    }
    .content{
        position: absolute;
        top: 0;
        width: 100%;
        background-color: #abcdef;
        transition: all 0.016s linear;

    }
    .content div{
        height: 100px;
        background-color: #f40;
    }
    .bar_box{
        position: absolute;
        right: 90px;
        top:50%;
        transform: translateY(-50%);
        height: 500px;
        width: 4px;
        border-radius: 2px;
        background-color: rgba(25, 25, 25,.7);
        overflow: hidden;
    }
    .bar{
        position: absolute;
        top:0;
        height: 20px;
        width: 100%;
        border-radius:2px; 
        background-color: rgb(197, 179, 179);
        transition: all 0.016s linear;
    }
    </style>
</head>
<body>
    <div class="wrapper">
        <div class="view_box">
            <div class="content">
               <div>這是內容</div>
               <div>這是內容</div>
               <div>這是內容</div>
               <div>這是內容</div>
               <div>這是內容</div>
               <div>這是內容</div>
               <div>這是內容</div>
               <div>這是內容</div>
               <div>這是內容</div>
               <div>這是內容</div>
               <div>這是內容</div>
               <div>這是內容</div>
               <div>這是內容</div>
               <div>這是內容</div>
               <div>這是內容</div>
               <div>這是內容</div>
               <div>這是內容</div>
               <div>這是內容</div>
               <div>這是內容</div>
               <div>這是內容</div>
            </div>
        </div>
        <div class="bar_box">
            <div class="bar"></div>
        </div>
    </div>

    <script>
        
        var wrapper = document.getElementsByClassName('wrapper')[0];
        //獲取展現內容區的區域
        var view_box = document.getElementsByClassName('view_box')[0];
        //獲取展現內容區的區域的大小
        var view_box_height = view_box.offsetHeight;
        //獲取內容區
        var content = document.getElementsByClassName('content')[0];
        //獲取內容區的實際高度
        var content_height = content.offsetHeight;
        //獲取滑道
        var bar_box = document.getElementsByClassName('bar_box')[0];
        //獲取滑道的高度
        var bar_box_height = bar_box.offsetHeight;
        //獲取滾動條
        var bar = document.getElementsByClassName('bar')[0];
        
        //求 滾動條的高度

        //當展現的內容區的大小恰好展現內容區域時,滾動條的高度就是滑道的高度
        if(view_box_height / content_height < 1) {
            bar.style.height = (view_box_height / content_height) * bar_box_height + 'px';
        } else {
            bar.style.height = bar_box_height + 'px';
        }

        //綁定事件(作兼容處理)
        wrapper.onmousewheel = function (e){
        //    e.wheelDelta < 0 //(-120)  向下
        //    e.wheelDelta > 0 //(120)  向上
        scrollRoll(e);
        }
        //兼容  Firefox 
        wrapper.addEventListener('DOMMouseScroll',function (e) {
            // e.detail > 0  //(3)  滑輪向下滾動
            // e.detail < 0  //(-3)  滑輪向上滾動
            scrollRoll(e);
        },false)


        function scrollRoll (e) {
            e = e || window.event;
            if (e.detail > 0) {
                down();
            } else if (e.detail < 0) {
                up();
            }

            if (e.wheelDelta > 0) {
                up();
            } else if (e.wheelDelta < 0) {
                down();
            }
        }
        //滑輪向下滾動
        function down () {
            var speed = 8;
            if (bar.offsetTop >= bar_box_height - bar.offsetHeight) {
                bar.style.top = bar_box_height - bar.offsetHeight + 'px';
                //注意:內容區應該向上移動
                content.style.top = - (content_height - view_box_height) + 'px';
            } else {
                bar.style.top = bar.offsetTop + speed + 'px';
                content.style.top = - bar.offsetTop / (bar_box_height - bar.offsetHeight) * (content_height - view_box_height) + 'px';
            }
        }
        //滑輪向上滾動
        function up () {
            var speed = 8;
            if (bar.offsetTop <= 0) {
                bar.style.top = 0 + 'px';
                content.style.top = 0 + 'px';
            } else {
                bar.style.top = bar.offsetTop - speed + 'px';
                content.style.top = - bar.offsetTop / (bar_box_height - bar.offsetHeight) * (content_height - view_box_height) + 'px';
            }
        }
   </script>
</body>
</html>
相關文章
相關標籤/搜索