我注释掉了prev(), 默认都是向右自动轮播。如果要改成是往左轮播,只要在这里加一个一个配置选择就好了。自动循环都做好了,在此基础上点击翻页,也是很容易的事情了,给按钮邦定一个click事件,如果是右边的,就调用next()方法,反之则调用prev()方法。不过我这里没有这样做,因为考虑到后面我们还要做手势(鼠标)拖动翻页效果,我决定用事件代理来做。让事件统统都冒泡到包装容器上去处理,这也是提升性能的常用技巧之一。
fn.bindEvents = function(){ if(Device.desktop){ this.container.addEventListener('mousedown',this,false); this.container.addEventListener('mousemove',this,false); document.addEventListener('mouseup',this,false); }else{ this.container.addEventListener('touchstart',this,false); this.container.addEventListener('touchmove',this,false); document.addEventListener('touchend',this,false); } this.container.addEventListener('transitionend',this,false); this.container.addEventListener('click',this,false); }
为什么这里的addEventListener为什么是邦定this而不是一个函数呢?简单说,是因为上下文中有一个handleEvent方法,可以被监听函数自动捕获到,这个函数名是固定的,不明白的可以自行搜索这个函数名。
fn.handleEvent = function(e){ var type = e.type;<br> //注意这里边的this<br>}
这样做的好处是可以维持事件邦定的那个函数的上下文。简单说就是不用操心this的指向会变。
做完这一步,就可以做拖动翻页了。在pc上用鼠标,在手机上用手指,处理的方式都是一样的,监听按下,移动,释放这三个事件。按下的时候,记住初始坐标,移动的时候和这个坐标进行对比,计算出移动的距离,然后更新到移动的对象上(红框)。这里边有几个地方需要注意:
1. 如果移动的时候,不是直线,x坐标和y坐标都有改变,是判断成水平拖动还是垂直拖动?
2. 在pc上,如何判断是拖动,拖出屏幕外了怎么处理?
3. 反弹怎么做?
对于第1点,可以比较两个方向距离的大小,谁大听谁的。如果指向了是水平滚动,那么可以直接忽略竖直方向的变化。
对于第2点,可以把监听mouseup放到document上去,最好加一个移动的距离大小判断,如果超过容器的大小,就当作是释放了,该反弹的反弹,该滑页的滑页。
对于第3点,在拖动释放的时候,判断移动距离,比如拖动的距离小于屏宽的1/3,就反方向translate相应的距离回去,甚至都不用关心这个距离,反正这时的activeIndex没有更新的,直接回到这个activeIndex对应的页就算是反弹了。代码就是这样:
fn.stop = function(){ this.axis.x = 0; translate3d(this.wrap,this.slideWidth*this.activeIndex); transition(this.wrap,this.params.speed); }
接下来就是做页码指示器了,这个简单,翻页成功之后就更新一下对应的小点就是了。由于我们人为的插了两个页面进去,索引数和页码数就对应不起来了,实际参与滚动的图片有6张,但是只能显示4个点。我做的时候走了一些弯路,现在总结起来无非就是两点:
1. 给小圓点加一个属性用来标记是哪个页面。用于处理点击滚动的时候,知道是跳到哪个页面。
2. 用一个数组来保存页面索引,比如【3,0,1,2,3,1】,这样当自动或拖动翻页的时候,可以通过activeIndex的值,确定要高亮哪个页码指示器。(小圆点)
也可能还有更好的方法,暂时就先这样实现吧。先把功能做出来,后面有时间,有灵感了再去优化。
到这里,几本上就做完了,只是还要再完善一些边际情况,比如一张图都没有的情况,默认参数的处理等。
思考
除了这个方法之外是不是有其它解决方法呢?比如下图这样,红框中只放三张,多余的叠在屏后面,移动的时候不是移红框,而是真实的移动图片?
这种方法也是可以行的通的,不过我在尝试的时候,发现这种方法在手机上有些卡顿,在电脑上看,容器边框会有闪动,原因没有深入去查了。
咳!咳..,下载源码请上号称全球最大的同性交友网站github.com ,在线预览无图片版本
小结一下
写到这里的时候,主体的逻辑差不多就实现了, 只用了大约三百多行代码,虽然很精简,但是这里还有许多东西没有考虑进去,比如竖直方向的滚动,兼容性问题等等。通过画草图的方法来帮助理清思路,遇到困难,可以借鉴别人的实现方法,参考但不是原封不动的复制粘贴。代码组织要考虑扩展性和可读性,先从程序的骨架写起,然后再去写方法,处理细节问题。通过动手实践,可以发现一些看似简单的东西,做起来也不是那么容易的。自己做出来之后,再去看别人写的好的代码,就会知道人家哪些地方比我实现的好,有哪些值得学习的地方。