移动端无缝滚动兼拖动插件

需求分析:
1、无缝滚动
2、触摸拖动

先上html代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<title>图片点击滑动</title>
<style>
body{padding: 0;margin: 0;}
li,ol,ul{margin: 0;list-style: none;padding: 0;}
div#l-btn{left: 0;color: gray;}
div#r-btn{right: 0;color:brown;cursor: pointer;}
.nav-container{position: relative;width: 98%;height:10em;overflow: hidden;margin: 2em auto;}
.nav{position: absolute;top: 0;left:0;}
.nav li{float: left;width:8em;text-align: center;}
.nav li img{width: 100%;height: auto;}
.nav span{font-size: 1.6em;}
</style>
</head>
<body>
<div class="nav-container">
<ul class="nav" id="nav">
<li><img src="img/hb1.jpg" /><br/><span>1</span></li>
<li><img src="img/hb2.jpg" /><br/><span>2</span></li>
<li><img src="img/hb3.jpg" /><br/><span>3</span></li>
<li><img src="img/hb4.jpg" /><br/><span>4</span></li>
<li><img src="img/hb2.jpg" /><br/><span>5</span></li>
<li><img src="img/hb3.jpg" /><br/><span>6</span></li>
<li><img src="img/hb4.jpg" /><br/><span>7</span></li>
<li><img src="img/hb2.jpg" /><br/><span>8</span></li>
</ul>
</div>
</body>
</html>

无缝滚动的原理呢,就是把ul容器内的全部li标签clone追加到后面,来来来,献上丑图分析一下:
示意图1
当它自右向左滚动的距离大于红框宽度的一半的时候,我们就让它的tanslateX=0;因为此处刚好跟初始位置重叠,所以当我们还原到初始位移为0的时候就不会出现跳跃感了。
js代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
var UcanSlide=function(ele,config){
this.config=config||{};
this.wrap=document.querySelector(ele);
this.ul_wrap=this.wrap.querySelector('ul');
this.ul_wrap.innerHTML+=this.ul_wrap.innerHTML;
this.oli=this.ul_wrap.querySelectorAll('li');
this.len=this.oli.length;
this.marginRight=this.config.marginRight||15;//设置li标签的右边距
this.autoScroll=this.config.autoScroll||true;//设置容器的滚动状态
this.scrollStep=this.config.scrollSpeed||2;//设置容器滚动的步长
this.setTime = null;
this.warp_width=this.wrap.offsetWidth;
this.ul_wrap_width=0;
this.init();
}
UcanSlide.prototype.init=function(){
var _this=this;
for(var i=0;i<this.len;i++){
this.oli[i].style.marginRight=this.marginRight+'px';
this.ul_wrap_width+=(this.oli[i].offsetWidth+this.marginRight);
}
this.ul_wrap.style.width=this.ul_wrap_width+'px';
if(this.ul_wrap_width<this.warp_width){
return;
}
if(this.autoScroll){
//执行无缝滚动
this.setTime=setInterval(function(){
  _this.move();
},this.scrollSpeed);
}
}

UcanSlide.prototype.move=function(){
    if(this.autoScroll){
      //自由滚动状态(自右向左)
      this.dirX=this.dirX-this.scrollStep;
      if(this.dirX<-this.ul_wrap_width/2||this.dirX>0){
        this.dirX=0;
      }
    }else{
      //拖动状态
      if(this.dirX<-this.ul_wrap_width/2){
        this.dirX=0;
      }else if(this.dirX>=0){
        this.dirX=-this.ul_wrap_width/2;
      }
    }
    this.ul_wrap.style.webkitTransform='translate3d('+this.dirX+'px,'+'0px,0px)';
};
new UcanSlide('.nav-container');

无缝滚动部分差不多就是这样子了,现在再加上一个需求,就是当手指放在滚动部分时,可以拖动,手指离开时滚动继续。

此时,我们需要做的就是记录当前移动的位移:this.dirX;

注册touchstar、touchmove和touchend事件。

1
2
3
4
5
6
7
8
9
10
//在init()函数里面添加
this.ul_wrap.addEventListener('touchstart',function(e){
_this.touchStart(e);
},false);
this.ul_wrap.addEventListener('touchmove',function(e){
_this.touchMove(e);
},false);
this.ul_wrap.addEventListener('touchend',function(e){
_this.touchEnd(e);
},false);

touchStart():主要功能就是清除循环滚动的计时器和记录手指当前触摸屏的x坐标;

1
2
3
4
5
UcanSlide.prototype.touchStart=function(e){                    
e.preventDefault();
clearInterval(this.setTime);
this.startX=e.targetTouches[0].clientX;
};

touchMove():累加每次移动的位移

1
2
3
4
5
6
7
UcanSlide.prototype.touchMove=function(e){
e.preventDefault();
this.autoScroll=false;
this.dirX+=e.targetTouches[0].clientX-this.startX;
this.startX=e.targetTouches[0].clientX;//记录前一次触屏坐标
this.move();
};

touchEnd():手指离开后开始滚动

1
2
3
4
5
6
7
UcanSlide.prototype.touchEnd=function(e){
var _this=this;
this.autoScroll=true;
this.setTime=setInterval(function(){
_this.move();
},this.scrollSpeed);
};

最后调用,传入容器的class或者id都可以。

1
new UcanSlide('.nav-container');

效果演示:
示意图2

热评文章