css和js实现虚拟滚动条
场景:在开发某个需求时,产品提出卡券横向滚动时原有滚动条太丑,让UI设计了个小滚动条,当卡券滑动时,该小滚动条也可以跟着滚动
想法:一开始是想通过css实现滚动条的样式变化,用::-webkit-scrollbar 相关属性达到更改滚动条的目的,但是用这种方式没法控制横向滚动条的宽度,达不到产品的要求。
解决:纯css是没法实现了,只能通过css和js实现。
html: 先写个ul嵌套li模拟滚动卡券的效果,同级增加一个虚拟滚动条div,该div内嵌一个div(scrollBar)代表滚动的滑块;
<ul class="scrollReal" id="scrollReal" @touchmove="slideMove()">
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<div class="scrollFake">
<div class="scrollBar" :style="{left:slideIconLeft+'px'}"></div>
</div>
css: 先写虚假滚动条的样式,left是个变量,用js实现left的变化
.scrollReal{
width: 300px;
overflow-x: scroll;
white-space: nowrap;
}
.scrollReal li{
display: inline-block;
width: 110px;
height: 100px;
border: 1px solid #ccc;
margin-right: 10px;
}
.scrollFake{
width: 200px;
height: 20px;
border-radius: 10px;
position: relative;
border: 1px solid #ccc;
}
.scrollBar{
position: absolute;
height: 100%;
width: 30px;
border-radius: 10px;
left: 0;
background: pink;
}
js: 实现虚拟滚动条滑块的滚动,通过改变left的值实现。
1、如上面的html所示,ul的宽度是固定的,li累加起来是卡片总宽度包括margin值,滑动的比例scale为ul左移偏移量scrollLeft除以(卡片总宽度-ul宽度),当ul偏移量scrollLeft==卡片总宽度-ul宽度)时,就代表滑到尽头了。
2、滑动的left的值为scale*虚拟滚动条的宽度,有一点要注意:如果滑动到了(虚拟滚动条的宽度-滑块的宽度),就可以固定left的值为(虚拟滚动条的宽度-滑块的宽度),这样就不会出现滑块溢出的情况。
// 滑块动态left值
var slideLeft = 0;
//动态计算滑块left
slideMove(){
//虚拟滚动条的总宽度,滑块宽度,css中设置的值
var slideTotal=200, slideIcon=30;
//卡片总宽度+margin,css中设置的值
var liTotalWidth = 110*4+10*4;
//ul
var dom=document.getElementById('scrollReal');
//滑动的比例,ul左偏移量/(卡片总宽度-ul宽度)
var scale=dom.scrollLeft/(liTotalWidth-dom.offsetWidth);
//当前虚拟滚动条滑块的left大小,以同等比例*虚拟滚动条总宽度,就可以实现同步滑动
this.slideLeft = scale*slideTotal;
//如果滑动到了(虚拟滚动条的宽度-滑块的宽度),就固定left为(虚拟滚动条的宽度-滑块的宽度)
if(this.slideLeft >= slideTotal-slideIcon){
this.slideLeft = slideTotal-slideIcon;
}
}