可以无限循环,到达最大页时,自动轮换到第0个,能实现无限循环。。
1、手指跟随和不跟随 isFollow
2、自动轮换 loop
3、是否延迟加载加载 lazyLoad
话不多说,请看源码:zepto.touchCarousel.js
(function($){
/**
*css3 Touch Scroll
*
* @author: zhangnan
*
* @param {Object} options;
* @config {zepto} options.$el //外围容器 选择器或者element
* @config {array} options.pages //填充每一页的内容 Element || string || function
* @config {Number} options.animTime //动画时间,默认为500
* @config {Function} options.beforechange //动画完成之前回调函数
* @config {Function} options.afterchange //动画完成之后回调函数
* @isFollow {Boolean} obtions.isFollow //是否跟随,默认false
* @isFollow {Boolean} obtions.loop //自动循环的时间/ms
*
*
*
*
*/
var TouchScroll=function(options){
this.$el= $(options.$el);
this.options= $.extend(arguments.callee.defaultData, options);
this.options._lazyLoad= !this.options.loop && this.options.lazyLoad;
this._wrapLeftIndex= this.options._wrapLeftIndex;
this._curIndex= this.options._curIndex;
this._initContainer();
this._initNodes();
this._init();
};
//默认参数
TouchScroll.defaultData= {
isFollow: false,
animTime: 500,
_curIndex: 0, //当前索引
_wrapLeftIndex: 0, //是外围动画节点的移动单位距离
loop: 0,
loopDir: 1,
pages: [],
lazyLoad: false,
beforechange: function(){
console.log('berore');
},
afterchange: function(){
console.log('afterchange');
},
}
$.extend(TouchScroll.prototype,{
//顾名思义
_init:function(){
var self=this;
self.touchEnabled= true;
addEventListener('onorientationchange' in window ? 'orientationchange' : 'resize', function(e){
});
this.options.isFollow ? this.initTouchFollow() : this.initTouch();
if(this.options.loop){
var dirfoo= self.loopDir > 0 ? 'toLeft' : 'toRight';
(self.autoLoop= function(){
self.timeout= setTimeout(function(){
self[dirfoo]();
}, self.options.loop)
})();
}
this.$container[0].addEventListener('webkitTransitionEnd', self, false);
return this;
},
_initContainer: function(){
this.$el.css({'overflow': 'hidden'});
this._contentWidth= this.$el[0].clientWidth;
},
_initNodes: function(){
var i= 0, nodes, length, left, contentWidth= this._contentWidth, self= this,
reg= /<\//g,
html= this.$el.html();
if(this.options._lazyLoad)
reg= /<\//;
html= html.replace(reg, function($a){
return self.getpage(i++)+$a
});
this.$el.html('<div style="display: -webkit-box;-webkit-user-select: none;-webkit-transition: -webkit-transform '+this.options.animTime+'ms cubic-bezier(0, 0, 0.25, 1)">'+
html
+
'</div>');
nodes= this.nodes= (this.$container= this.$el.children()).children();
this.maxIndex= (length= this.nodesLength= nodes.length) -1;
var bestDest= Math.ceil(length/2);
var nodesAry= self._nodes=[];
nodes.forEach(function(node, index){
left= index< bestDest ? index : -(length- index);
nodesAry.push({node: node, left: left, index: index});
node.style.cssText+= ';-webkit-transform: translate(-'+(index)+'00%, 0) translate3d('+left*contentWidth+'px, 0px, 0px); 100%;';
})
nodesAry.sort(function(a, b){
return a.left- b.left;
});
},
_setNodesTranslate: function(dir){
var into,
out,
bestLeft,
nodes= this._nodes,
node,
contentWidth= this._contentWidth,
maxIndex=this.nodesLength-1,
curIndex= this._curIndex,
curpage;
if(dir==0)
return;
if(dir<0){
into= 'unshift';
out= 'pop';
bestLeft= nodes[0].left -1;
}else{
into= 'push';
out= 'shift';
bestLeft= nodes[maxIndex].left+ 1;
}
node= nodes[out]();
node.left= bestLeft;
nodes[into](node);
node.node.style.cssText= node.node.style.cssText.replace(/translate3d\(([-\d]+)px/g, 'translate3d\('+
bestLeft* contentWidth
+'px');
if(this.options._lazyLoad){
curpage= this.nodes[curIndex];
!curpage.firstElementChild && (curpage.innerHTML= this.getpage(curIndex));
}
},
toLeft: function(dir){
this.move(-1);
},
toRight: function(){
this.move(1);
},
toCurrent: function(){
this.move(0);
},
getpage: function(index){
var page= this.options.pages[index];
return $.isFunction(page) ? page() : page instanceof Element ? page.outerHTML : page;
},
handleEvent: function(e){
if(e.type==='webkitTransitionEnd'){
this.options.afterchange(this._curIndex);
this.touchEnabled= true;
this.options.loop && this.autoLoop();
}
},
move: function(dir){
var left= this._wrapLeftIndex= this._wrapLeftIndex-dir, res;
this._curIndex= (res= this._curIndex+ dir) < 0 ? this.maxIndex : res > this.maxIndex ? 0 : res;
this._setNodesTranslate(dir);
this.options.beforechange(this._curIndex);
this.setLeft(left * this._contentWidth);
},
setLeft: function(left){
this.$container.css({'-webkit-transform': 'translate3d('+ left +'px, 0px, 0px)'});
},
setAnimTime: function(time){
this.$container.css('-webkit-transition', '-webkit-transform '+time+'ms cubic-bezier(0, 0, 0.25, 1)');
},
//一看就懂
touchEv:(function(){
var isTouchPad = (/hp-tablet/gi).test(navigator.appVersion),
hasTouch='ontouchstart' in window && !isTouchPad;
return {
hasTouch:hasTouch,
START_EV:hasTouch ? 'touchstart' : 'mousedown',
MOVE_EV:hasTouch ? 'touchmove' : 'mousemove',
END_EV:hasTouch ? 'touchend' : 'mouseup'
}
})(),
//不跟随动画注册
initTouch:function(){
var now=null,
touch={},
self=this,
timeout,
touchEv=this.touchEv;
this.$el.on(touchEv.START_EV,function(e){
if(!self.touchEnabled)
return ;
if(e.touches.length!==1)
return ;
// self.stopLoop();
touch.x1= e.touches[0].clientX;
touch.y1= e.touches[0].clientY;
timeout=setTimeout(function(){
timeout=null;
},800);
}).on(touchEv.MOVE_EV,function(e){
if(!self.touchEnabled)
return ;
if(timeout){
touch.x2= e.touches[0].clientX;
touch.y2= e.touches[0].clientY;
dir=self.swipeDirection(touch.x1,touch.x2,touch.y1,touch.y2);
if(dir=='Left' || dir=='Right')
e.preventDefault();
}
})
$(document).on(touchEv.END_EV,function(e){
if(!self.touchEnabled)
return;
if(timeout && touch.x2 && Math.abs(touch.x1 - touch.x2) > 5){
self.touchEnabled= false;
if(dir=='Left'){
self.toRight();
}else if(dir=='Right'){
self.toLeft();
}
};
touch={};
});
return this;
},
//跟随动画注册
initTouchFollow:function(){
var touchEv=this.touchEv,
self=this,
scrolling=null,
startX=0,
startY=0,
moveX=0,
moveY=0,
baseX=0,
distX,
newX,
// startTime,
dir=0,
currentLeft= 0,
transX;
this.$el.on(touchEv.START_EV,function(e){
if(!self.touchEnabled && e.touches.length!=1)
return ;
if(!touchEv.hasTouch)
e.preventDefault();
self.setAnimTime(0);
// self.stopLoop();
scrolling=true;
moveRead=false;
startX=e.touches[0].clientX;
startY=e.touches[0].clientY;
baseX=startX;
newX= self._wrapLeftIndex* self._contentWidth;
//startTime=e.timeStamp;
dir=0;
}).on(touchEv.MOVE_EV,function(e){
if(!scrolling || !self.touchEnabled)
return ;
var moveX=e.touches[0].clientX,
moveY=e.touches[0].clientY;
if(moveRead){
distX=moveX-baseX;
self.setLeft(newX+=distX);
dir= distX>0 ? 1 : -1;
baseX=moveX;
}else{
var changeX=Math.abs(moveX-startX),
changeY=Math.abs(moveY-startY);
if((changeX/changeY)>1){
e.preventDefault();
e.stopPropagation();
moveY= null;
moveRead=true;
}else if(changeY>5){
scrolling=false;
moveY= null;
self.setAnimTime(self.options.animTime);
}
};
});
$(document).on(touchEv.END_EV,function(e){
setTimeout(function(){
// self.setLoop();
},100);
if(!scrolling || !self.touchEnabled)
return ;
self.touchEnabled= false;
scrolling=false;
transX = baseX-startX;
self.setAnimTime(self.options.animTime);
if(transX > 50){
self.toLeft(null, 300);
}else if(transX < -50){
self.toRight(null, 300);
}else{
self.toCurrent(100);
}
scrolling=
startX=
startY=
moveX=
moveY=
baseX=
distX=
newX=
dir=
transX=null;
}).on(touchEv.START_EV, function(e){
// self.stopLoop();
})
return this;
},
swipeDirection:function(x1, x2, y1, y2){
var xDelta = Math.abs(x1 - x2), yDelta = Math.abs(y1 - y2)
return xDelta >= yDelta ? (x1 - x2 > 0 ? 'Left' : 'Right') : (y1 - y2 > 0 ? 'Up' : 'Down');
},
});
//添加到Zepto
$.fn.touchCarousel=function(options){
options.$el = this;
var instance = new TouchScroll(options);
return instance ;
}
})(Zepto);
html部分 index.html
<html>
<head>
<title>
carousel by 一只柯楠
</title>
<style type="text/css">
*{
-webkit-tap-highlight-color: rgba(0,0,0,0);
-webkit-user-select: none;
-webkit-touch-callout: none;
-webkit-user-drag: none;
padding: 0;
margin: 0;
}
#carousel img{
420px;
}
#carousel {
420px;
margin: 0 auto;
border: 20px solid red;
}
#carousel div{
background: red;
min-height: 150px;
position: relative;
}
#carousel div span{
position: absolute;
height: 100%;
100%;
font-size: 80px;
line-height: 400px;
font-weight: bold;
text-align: center;
}
</style>
</head>
<body>
<div id="carousel">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<script type="text/javascript" src="zepto.js"></script>
<script type="text/javascript" src="zepto.touchscroll.js"></script>
<script type="text/javascript">
var html= [], len= 6;
for(var i=1; i<=len; i++){
html.push('<a href="javascript:void(0);" ><span>'+i+'</span><img src="img/'+i+'.jpg"></a>');
}
$('#carousel').touchCarousel({
: 5000,
pages:html ,
isFollow: true
}
);
</script>
</body>
</html>
。。。。欢迎吐槽