最近在准备面试看到这个面试题,感觉貌似不少公司都会问一下相关问题,所以在这简单实现一下
页面如下
.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>
大概说一下思路
- 首先分为四个部分:最外层容器parentDom ,内容盒子contentDom ,bar的容器盒子barboxtDom 和bar按钮
- 滑块的高度/bar的容器盒子的高度 = 可视容器(最外层容器)高度/内容盒子的高度,首先前三者可知,从而可以得出bar的高度
- 滑块可移动范围为器容器内,具体范围是 top为 0 到 bar的容器盒子的高度 - bar的高度
- bar下移则内容向上移动展示,所以 bar与内容盒子两者定位top相反
- 鼠标移出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()