原生js实现模拟滚动条

最近在准备面试看到这个面试题,感觉貌似不少公司都会问一下相关问题,所以在这简单实现一下

页面如下

 .parent {
        width: 300px;
        height: 200px;
        margin: 0 auto;
        background: rgba(0,0,0,.4);
        overflow:hidden;
        position:relative;
        border:1px solid #000;
        -webkit-user-select:none; 
       -moz-user-select:none; 
       -ms-user-select:none; user-select:none;
    }
    input {
        display: block;
        margin: 0 auto;
    }
    #content {
        width:300px;
        min-height: 200px;
        line-height: 30px;
        position:absolute;
        top:0;left:0;
    }
    #barbox{
        width:20px;
        position:absolute;
        right:0;
        height:100%;
        top:0;
        background-color: #fff;
        opacity: 0;
    }
    #bar{
        width:100%;
        position: absolute;
        top:0;
        height:20px;
        background-color: pink;
    }
</style>
<body>
    <div id="parent" class="parent">
        <div id="content" class="content">
            <ul>
                <li>1</li>
                <li>2</li>
                <li>3</li>
                <li>4</li>
                <li>5</li>
                <li>6</li>
                <li>7</li>
                <li>8</li>
                <li>9</li>
                <li>10</li>
            </ul>
        </div>
        <div id="barbox" class="barbox">
            <div  id="bar" class="bar"></div>
        </div>
    </div>
</body>

大概说一下思路在这里插入图片描述

  1. 首先分为四个部分:最外层容器parentDom ,内容盒子contentDom ,bar的容器盒子barboxtDom 和bar按钮
  2. 滑块的高度/bar的容器盒子的高度 = 可视容器(最外层容器)高度/内容盒子的高度,首先前三者可知,从而可以得出bar的高度
  3. 滑块可移动范围为器容器内,具体范围是 top为 0 到 bar的容器盒子的高度 - bar的高度
  4. bar下移则内容向上移动展示,所以 bar与内容盒子两者定位top相反
  5. 鼠标移出barboxtDom 与 鼠标松开时不记录鼠标移动轨迹

然后根据以上逻辑得出一下代码

js代码

var barObj = {
            parentDom : document.getElementById('parent'),
            contentDom : document.getElementById('content'),
            barboxtDom : document.getElementById('barbox'),
            barDom : document.getElementById('bar'),
            parentH : null,
            contentH : null,
            barboxtH : null,
            contentScrollH:null,
            barPositionY:0,//滑块当前位置
            barLimits:null,//滑块最大定位
            contentLimits:null,//内容最大定位
            mouseStartTop:null,//鼠标开始的位置
            mouseScrollH:null,//鼠标移动的距离(Y)
            init:function(){
                this.parentH = this.parentDom.clientHeight;
                this.contentH = this.contentDom.clientHeight;
                this.barboxtH = this.barboxtDom.clientHeight;
                //得到bar的高度
                let barH = this.parentH/this.contentH*this.barboxtH;
                //bar的top最大值
                this.barLimits = this.barboxtH - barH;
                //内容的top最大值的绝对值
                this.contentLimits = this.contentH - this.parentH;
                this.barDom.style.height = barH+'px'; 
                if (document.addEventListener) { 
                    this.barDom.addEventListener('mousedown', this.start);
                    this.parentDom.addEventListener('mouseover', this.moveover);
                    this.parentDom.addEventListener('mouseout', this.moveout);
                }
            },
            start:function(event){//鼠标按下时开始监听鼠标移动事件
                barObj.mouseStartTop = event.clientY
                barObj.barDom.addEventListener('mousemove', barObj.move);
                barObj.barDom.addEventListener('mouseup', barObj.stop);
                barObj.barDom.addEventListener('mouseout', barObj.stop);
            },
            move:function(event){//鼠标移动时的逻辑
                barObj.mouseScrollH = event.clientY - barObj.mouseStartTop;
                console.log(barObj.mouseScrollH)
                let contentPositionY = 0;
                if((barObj.mouseScrollH + barObj.barPositionY)<0){
                    barObj.barPositionY = 0
                    barObj.barDom.style.top = '0px';
                    barObj.contentDom.style.top = '0px';
                }else if((barObj.mouseScrollH + barObj.barPositionY)>barObj.barLimits){
                    barObj.barPositionY = barObj.barLimits
                    barObj.barDom.style.top = barObj.barLimits+'px';
                    barObj.contentDom.style.top = -barObj.contentLimits+'px';
                }else{
                    contentPositionY = (barObj.mouseScrollH + barObj.barPositionY)/barObj.barLimits  * barObj.contentLimits;
                    barObj.barDom.style.top = (barObj.mouseScrollH + barObj.barPositionY)+'px';
                    barObj.contentDom.style.top = -contentPositionY+'px';
                }

            },
            stop:function(envet){//鼠标移出barboxtDom 与 鼠标松开时解除鼠标移动的监听
                barObj.barPositionY = barObj.mouseScrollH + barObj.barPositionY;
                barObj.barDom.removeEventListener('mousemove', barObj.move);
                barObj.barDom.removeEventListener('mouseup', barObj.stop);
                barObj.barDom.removeEventListener('mouseout', barObj.stop);
            },
            moveover:function(){
                barObj.barboxtDom.style.opacity = '.7';
                document.onmousewheel = barObj.scrollFunc;
            },
            moveout:function(){
                barObj.barboxtDom.style.opacity = '0';
                document.onmousewheel = null;
            },
            scrollFunc : function (e) { //滚动滑轮时运行的方法
                console.log(e.deltaY)
                if(e.deltaY>0){//e.deltaY下滑为正,上滑为负
                    barObj.barPositionY+=2;
                }else{
                    barObj.barPositionY-=2;
                }
                if(barObj.barPositionY<0){
                    barObj.barDom.style.top = '0px';
                    barObj.contentDom.style.top = '0px';
                    barObj.barPositionY = 0;
                }else if(barObj.barPositionY>barObj.barLimits){
                    barObj.barDom.style.top = barObj.barLimits+'px';
                    barObj.contentDom.style.top = -barObj.contentLimits+'px';
                    barObj.barPositionY = barObj.barLimits;
                }else{
                    contentPositionY = barObj.barPositionY/barObj.barLimits  * barObj.contentLimits;
                    barObj.barDom.style.top = barObj.barPositionY +'px';
                    barObj.contentDom.style.top = -contentPositionY+'px';
                }

            },
            topF:function(){
                barObj.barDom.style.top = '0px';
                barObj.contentDom.style.top = '0px';
                barObj.barPositionY = 0;
            }
        }
        barObj.init()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值