从前只做过PC端轮播组件,实现方式也是margin负值和setTimeout。前一阵看到一个比较精简的移动端轮播组件的实现,用translate代替margin负值,并且添加了对touch事件的处理。在这里总结一下这个组件的实现。
所有的li绝对定位于容器左上角,宽度100%,高度100%。
1.组件init步骤:
1)如果设定了连续轮播,则复制first slide到最后一帧后,last slide到第一帧前。
2)计算轮播距离(幻灯片宽度或高度。下面都假设是宽度)width.
3)为每一个li设置transition属性(好像没用)
4)第0个li向左translate width, 第1个li不移动,第2个li向右translate width, 依次类推。这样所有的幻灯片从层叠到排列。
5)调用antoSlide()开始轮播
2. autoSlide的实现:
1)停止autoSlide定时器
2)setInterval设置每speed ms执行一次fnSlide('next'),播放下一slide, 每次播放300ms. 定时器指针赋值给autoSlide.
3. fnSlide实现。
组件有一个全局_index. 每次播放根据_index的值。
1)如果播放下一slide(next), _index++
如果播放上一slide, _index--
如果固定某个slide, _index = _slide
也可能以上情况都不是,那就是默认播放完当前_index对应的slide. 这种情况是针对当前slide因为触摸事件停止播放而后又恢复播放的情况,下文将描述。
2)如果是循环播放:
如果当前已到最后一幅幻灯片且仍需播放下一幻灯片,则正常播放下一幅幻灯片,执行fnScroll(300),然后设置_index = 0;300ms以后执行fnScroll(0)将ul瞬间移动到第一幅幻灯片。 //播放的是位于最后的第一幅幻灯片,300ms的时间是自定义。
如果当前已到第一幅幻灯片且仍需播放上一幅幻灯片,则正常播放上一幅幻灯片,执行fnScroll(300), 然后设置_index = length - 1; 300ms以后执行fnScroll(0)将ul瞬间移动到最后一幅幻灯片。//播放的是位于最前面的最后一幅幻灯片,300ms可自定义。
如果以上两种情况都不是,则执行fnScroll(300)正常滚动。
3)如果不是循环播放:
如果当前已到最后一幅且向后,设置index = 0, 如果是第一幅且向前,设置index = length - 1; 然后执行fnScroll(300);这样的效果是在300ms内幻灯片从第一幅快进到最后一幅或者从最后一幅迅速回退到第一幅,其实不是太好看。
3. fnScroll函数的实现
1)根据参数设置ul的transition时间为0或300ms等等
2)ul根据_index的值translate. 对于每一幅幻灯片,ul translate的距离是固定的,与translate开始时ul的位置无关。所以在触摸回调中,fnScroll可能只是移动了半幅幻灯片。
4. 对触摸事件的处理
1)touchstart:
isScrolling=undefined.
moveDistance = 0
记录startX与startY
2)touchmove:
暂停autoSlide;
计算已移动的距离moveDistance;
如果是首次移动,则根据x移动距离与y移动距离的大小判断是滚动还是滑动。如果是滚动则不作处理,如果是滑动,设置ul transition的时间为0
如果不是循环播放,已经到最后一幅幻灯片还要向后或者已到第一幅幻灯片还要向前,设置moveDistance = 0;
ul translate moveDistanc距离
3)touchend:
如果当前是滚动,则恢复autoSlide.
如果滑动距离小于50px,视作播放当前幻灯片,fnScroll('')
如果滑动距离大于50px,视作播放下一幅或上一幅幻灯片,fnScroll('next')或者fnScroll('prev');
恢复autoSlide.