可以无限循环,到达最大页时,自动轮换到第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>
。。。。欢迎吐槽