欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

原生JS实现滚动条

程序员文章站 2023-11-02 18:41:40
原生JS模拟滚动条 求滚动条的高度   可视内容区的高度 / 内容区的实际高度 = 滚动条的高度 / 滑道的高度 求内容区top的值   内容区距离顶部的距离 / (内容区的实际高度 可视内容区域的高度 ) = 滚动条距离顶部的距离 / ( 滑道的高度 滚动条的高度) 使用onm ......

原生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>