function translate3d(element,x,y) { x = x === undefined ? 0 : x; y = y === undefined ? 0 : x; element.style['-webkit-transform'] = 'translate3d(-'+x+'px,'+y+'px,0px)'; element.style['transform'] = 'translate3d(-'+x+'px,'+y+'px,0px)'; } function transition(element,time){ element.style['-webkit-transition-duration'] = time+'ms'; element.style['transition-duration'] = time+'ms'; }
x控制左右移动,y控制竖直移动(本例中暂不考虑),z固定(0px). 当x移动的距离是正数的时候,向左滚动--prev,为负数的时候向右滚动--next
fn.next = function(){ var activeIndex = ++this.activeIndex; translate3d(this.wrap,activeIndex*this.slideWidth); transition(this.wrap,this.params.speed); } fn.prev = function(){ var activeIndex = --this.activeIndex; translate3d(this.wrap,activeIndex*this.slideWidth); transition(this.wrap,this.params.speed); }
由于图片数量是有限的,不能一直滚动,如果到头了,需要做一些处理。因此需要判断activeIndex(当前显示的图片索引)的值。如果到了最右边就不能再允许滚动了。
var activeIndex = this.lastIndex--;<br>if(activeIndex > this.lastIndex){ return; }
同理,到了最左边,也不能继续往左滚动了(听起来是一句非常正确的废话)
var activeIndex = --this.activeIndex; if(activeIndex < this.firstIndex){ return; }
现在要考虑自动滚动的情况,如果是自动轮播的情况,那就不能直接return; 要么当到达最右边的时候,activeIndex赋成firstIndex,当达到最左边的时候,activeIndex赋成lastIndex; 这样做的实际效果看起来就是像荡秋千一样,这显然不是我们想要的效果。要么跳到最前面重新开始,这做出来的实际效果一点也不连续。最后决定去看看swiper是怎么实现的。swiper的做法就是把第一张复制一份放到最后面,把最后一张复制一份插到最前面。 如下图所示:
第一张和第四张都被复制了一份。对应的代码如下:
fn.createLoopItems = function(){ var lastItem = this.slides[this.lastIndex]; var firstItem = this.slides[this.firstIndex]; var prevItem = lastItem.cloneNode(true); var nextItem = firstItem.cloneNode(true); var sliderCount = this.sliderCount+2; var slideWidth = this.slideWidth; this.slideStack.push(this.firstIndex); this.slideStack.unshift(this.lastIndex); this.wrap.insertBefore(prevItem,firstItem); this.wrap.appendChild(nextItem); this.wrap.style.width = slideWidth * sliderCount + 'px'; translate3d(this.wrap,slideWidth); this.activeIndex += 1; this.sliderCount = sliderCount; this.lastIndex += 2; }
不得不承认这个做法很巧妙。随便我们往哪个方向翻,都不至于出现空白期。当翻到最未尾(数字4)的时候,还可以再翻一页,即第一张的复制品,虽然不是真的第一张,但是看起来就像是平滑的过渡到了第一张一样。不过这是临时的,我们需要在过渡完之后,立即回到真正的1的位置上去。因为我们实际上在未端只补了一张,翻完这一页,如果不进一步处理,还是会到头。这时,就是问题的关键了。当我们往右翻,从第四张翻到复制的第一张时,需要悄悄地,人不知,鬼不觉的把红框的位置移到1的真身上来。同时把activeIndex也置为图1的索引。那么问题又来了,怎么才能做到人不知鬼不觉的暗渡陈仓呢?其实很简单,只要把移位动画的时间改成0就可以了。关键代码如下:
transition(this.wrap,0);
不过这一步要在从4变为1,刚停下来的时候,立即执行。做早了,就会感觉是直接从4跳到1,没有动画效果,做晚了,就会出现空白,并因为索引溢出而报错。所以这里需要一个修复方法:
fn.fixedPrevLoop = function(){ var that = this; setTimeout(function(){ that.fixedLoop(that.lastIndex-1) },that.params.speed); }
或者:
this.container.addEventListener('transitionend',function(){<br> //监听动画结速之后再执行判断是否要修复<br>},false);
做完这一步,就看起来有连续滚动的效果了,在这个基础上实现自动轮播就好办了,只要用定时器,每隔一段时间就执行一下自身就可以了。代码如下:
fn.autoPlay = function(){ var that = this; if(!this.params.autoplay){ return; } this.timeId = setTimeout(function(){ that.next(); //that.prev(); that.autoPlay(); },this.params.delay); }