移动轮播图我看到两类,
一款是无线天猫的m.tmall.com和携程,实现了无缝轮播。
一款是蘑菇街的,没有实现无缝轮播。
我自己重写一个,类似天猫。不过功能上简单点,只实现支持触屏和无缝轮播。
1.页面代码
1 <!DOCTYPE html> 2 <html xmlns="http://www.w3.org/1999/xhtml" lang="UTF-8"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>基于jQuery的移动轮播图(支持触屏)</title> 6 <meta name="viewport" content="maximum-scale=1,initial-scale=1,user-scalable=0"> 7 <script type="text/javascript" src="http://sandbox.runjs.cn/uploads/rs/215/auboqjjr/jquery-1.8.2.min.js"></script> 8 <script type="text/javascript" src="http://sandbox.runjs.cn/uploads/rs/215/auboqjjr/zepto.min.js"></script> 9 <script type="text/javascript" src="http://sandbox.runjs.cn/uploads/rs/215/auboqjjr/touchslide-1.0.js"></script> 10 <style type="text/css"> 11 12 img 13 { 14 border:0; 15 *display:inline; 16 } 17 18 body{ 19 overflow:hidden; 20 margin:0 auto; 21 padding:0; 22 width: 100%; 23 height: 100%; 24 } 25 .WSCSlideWrapper{ 26 width:100%; 27 position: relative; 28 margin:0 auto; 29 cursor:move; 30 } 31 32 #WSCSlideWrapperTwo{ 33 width:90%; 34 position: relative; 35 margin:10px auto; 36 cursor:move; 37 } 38 39 </style> 40 41 42 </head> 43 <body> 44 <div class="WSCSlideWrapper" id="WSCSlideWrapper" > 45 <div> 46 47 <a><img src="http://sandbox.runjs.cn/uploads/rs/215/auboqjjr/1.jpg" /></a> 48 <a><img src="http://sandbox.runjs.cn/uploads/rs/215/auboqjjr/2.jpg" /></a> 49 <a><img src="http://sandbox.runjs.cn/uploads/rs/215/auboqjjr/3.jpg" /></a> 50 </div> 51 52 </div> 53 54 <div class="WSCSlideWrapper" id="WSCSlideWrapperTwo" > 55 <div> 56 <a><img src="http://sandbox.runjs.cn/uploads/rs/215/auboqjjr/1 (1).jpg" /></a> 57 <a><img src="http://sandbox.runjs.cn/uploads/rs/215/auboqjjr/1 (2).jpg" /></a> 58 <a><img src="http://sandbox.runjs.cn/uploads/rs/215/auboqjjr/1 (3).jpg" /></a> 59 <a><img src="http://sandbox.runjs.cn/uploads/rs/215/auboqjjr/1 (4).jpg" /></a> 60 </div> 61 62 </div> 63 <script type="text/javascript"> 64 <!-- 65 $(document).ready(function(){ 66 67 $(‘.WSCSlideWrapper‘).height($(‘.WSCSlideWrapper‘).width()*0.3); 68 $(‘#WSCSlideWrapperTwo‘).height($(‘#WSCSlideWrapperTwo‘).width()*1.5); 69 $(‘.WSCSlideWrapper‘).touchslide({timecontrol:3000}); 70 71 }); 72 73 74 // --> 75 76 </script> 77 </body> 78 </html>
2.js插件代码
1 /* 2 * touchslide 1.0 3 * Copyright (c) 2014 BowenLuo http://www.luobo.com/ 4 * Date: 2014-06-08 5 */ 6 (function($){ 7 $.fn.touchslide = function(options){ 8 var defaults = { 9 timecontrol:3000, 10 animatetime:300 11 } 12 var options = $.extend(defaults, options); 13 var timecontrol = options.timecontrol; 14 var animatetime = options.animatetime; 15 this.each(function(){ 16 var slideWrapper=$(this); 17 var slideImgWrapper = slideWrapper.children(‘div:eq(0)‘); 18 var slideAs = slideImgWrapper.children(‘a‘); 19 var slideImgs = slideAs.find(‘img‘); 20 $((slideImgWrapper.html().split("/a>")[0]+"/a>")).insertAfter(slideAs.last()); 21 slideAs = slideImgWrapper.children(‘a‘); 22 slideImgs = slideAs.find(‘img‘); 23 var imgcount = slideImgs.length; 24 var slideWrapperWidth = slideWrapper.width(); 25 var slideWrapperHeight = slideWrapper.height(); 26 slideWrapper.css({"overflow":"hidden"}); 27 slideWrapper.width(slideWrapperWidth); 28 slideWrapper.height(slideWrapperHeight); 29 slideImgWrapper.css({‘position‘:"absolute","overflow":"hidden"}); 30 slideImgWrapper.width(slideWrapperWidth*imgcount); 31 slideImgWrapper.height(slideWrapperHeight); 32 slideAs.css({‘position‘:"relative","float":"left","overflow":"hidden"}); 33 slideAs.width(slideWrapperWidth); 34 slideAs.height(slideWrapperHeight); 35 slideImgs.width(slideWrapperWidth); 36 slideImgs.height(slideWrapperHeight); 37 var st; 38 var sts; 39 sts = setTimeout(function(){ 40 timedCount(); 41 },timecontrol); 42 slideWrapper.hover(function(){ 43 stopCount(); 44 clearTimeout(sts); 45 }, 46 function(){ 47 sts = setTimeout(function(){ 48 timedCount(); 49 },timecontrol); 50 }); 51 Zepto(this).bind(‘touchmove‘, function(e) {e.preventDefault(); }); 52 Zepto(this).swipeLeft(function(){ 53 stopCount(); 54 slideImgWrapper.stop(true); 55 timedCount(); 56 }).swipeRight(function(){ 57 stopCount(); 58 slideImgWrapper.stop(true); 59 turnright(); 60 clearTimeout(sts); 61 sts = setTimeout(function(){ 62 timedCount(); 63 },timecontrol); 64 }); 65 66 function timedCount() 67 { 68 turnleft(); 69 clearTimeout(st); 70 st=setTimeout(function(){ 71 timedCount(); 72 },timecontrol); 73 } 74 75 function stopCount() 76 { 77 if (st !=""){ 78 clearTimeout(st); 79 } 80 } 81 var turnleftwidth = 0; 82 function turnleft(){ 83 turnleftwidth = turnleftwidth+slideWrapperWidth; 84 if(turnleftwidth>(imgcount-1)*slideWrapperWidth){ 85 slideImgWrapper.css({‘left‘:0}); 86 turnleftwidth = slideWrapperWidth; 87 slideImgWrapper.stop(true).animate({left:-turnleftwidth},animatetime); 88 }else{ 89 slideImgWrapper.stop(true).animate({left:-turnleftwidth},animatetime); 90 } 91 92 } 93 function turnright(){ 94 if(turnleftwidth==0){ 95 slideImgWrapper.css({‘left‘:-slideWrapperWidth*(imgcount-1)}); 96 turnleftwidth = slideWrapperWidth*(imgcount-2); 97 slideImgWrapper.stop(true).animate({left:-turnleftwidth},animatetime) 98 }else{ 99 turnleftwidth = turnleftwidth-slideWrapperWidth; 100 slideImgWrapper.stop(true).animate({left:-turnleftwidth},animatetime); 101 } 102 } 103 }); 104 }; 105 })(jQuery);
3.整体思路
a.创建显示窗口,显示容器大小位置自定义;
b.创立图片容器,通过改变图片容器的位置来改变显示窗口中展示的图片。
难点在于如何改变图片容器位置来显示需要的图片和无缝轮播。可以想象一下以前的胶带式电影,如果放映速度慢下来就跟图片轮播类似了。所以可以把图片容器看成胶带,图片就是其中的一帧图像,显示窗口就是电影屏幕。
如果以一个显示窗口的宽为一个单位,我们把图片水平排放在图片容器中,每张图片恰好占用一个显示窗口的宽高,有多少张图片,图片容器的宽就为多少个单位宽。然后使图片向左移动一个单位的距离,就可以展示下一张图片了。为了使图片展示效果更美观,我用了jquery的动画效果animate()来改变图片容器的位置。如果设定间隔多少时间图片容器左移一个单位,达到最后一张图片时,图片容器恢复到原始位置,进行下一轮移动。这样,就可以实现图片的水平轮播了。至于无缝轮播,我采取的做法是把第一张图片复制一份,放到所有图片的最后面。当移动到最后一张图片时,在下一次移动时先改变容器的left,让第一张图片被显示出来,因为这个动作很快,看起来好像并没有进行任何操作(达到欺骗眼球的效果,呵呵),然后使用animate显示第二张图片,在视觉上实现无缝轮播。从第一张图片右移到最后一张图片也与此类似。这里,会用到的主要知识点有:
(1).setTimeout和clearTimeout:
用于延迟执行、循环执行和终止循环。setTimeout延迟执行确定图片的显示时间,循环执行为了自动展示下一张图片。当需要停止轮播的时候就可以用clearTimeout来终止循环了。关于setTimeout和clearTimeout的具体用法,可以参照代码,这里就不再赘述了。
(2).jquery选择器:
无需多说,所有jquery动作的基础。
(3).jquery操作css:
为了保证使用的简单性,只需确定显示容器的样式(需确保overflow:hidden;插件中已设置),其子元素包括图片容器(这里只支持div标签slideWrapper.children(‘div:eq(0)‘))和图片及其链接的样式都在插件中确定,包括:保证图片水平排列,大小恰好为显示窗口的大小;确定图片容器的大小恰好容下所有图片。
(4).jquery添加元素insertAfter:
复制第一张图片到所有图片的最后面$((slideImgWrapper.html().split("/a>")[0]+"/a>")).insertAfter(slideAs.last())。
(5).jquery动画效果animate:
1 var turnleftwidth = 0; 2 3 var animatetime = 300; 4 function turnleft(){ 5 turnleftwidth = turnleftwidth+slideWrapperWidth; 6 if(turnleftwidth>(imgcount-1)*slideWrapperWidth){ 7 slideImgWrapper.css({‘left‘:0}); 8 turnleftwidth = slideWrapperWidth; 9 slideImgWrapper.stop(true).animate({left:-turnleftwidth},animatetime); 10 }else{ 11 slideImgWrapper.stop(true).animate({left:-turnleftwidth},animatetime); 12 } 13 14 } 15 function turnright(){ 16 if(turnleftwidth==0){ 17 slideImgWrapper.css({‘left‘:-slideWrapperWidth*(imgcount-1)}); 18 turnleftwidth = slideWrapperWidth*(imgcount-2); 19 slideImgWrapper.stop(true).animate({left:-turnleftwidth},animatetime) 20 }else{ 21 turnleftwidth = turnleftwidth-slideWrapperWidth; 22 slideImgWrapper.stop(true).animate({left:-turnleftwidth},animatetime); 23 }
其中imgcount为进行图片复制后图片的元素个数,slideWrapperWidth为显示窗口的宽。 turnleft()用于无缝左移,turnright()用于无缝右移。
现在来说说触屏支持。这俩天恰好在入手zepto.js,所以就用了里面的touch支持。如果可以的话,还是自己写touch事件。因为zepto.js好像不能获取touchmove的距离,所以无法实现触摸拖拽图片。这里我用了俩个触屏事件,左滑swipeLeft和右滑swipeRight。过程都是先停止原来的轮播,然后左移/右移一个单位,延迟一定时间后,再重新进行轮播。需要注意的是每一个滑动动作开始后都要先停止原来的所有延迟事件和循环事件。
关于zepto.js,官方标准版是不支持touch的。可以去github下载压缩包,里面有所有支持的模块。我用的zepto.js,是经过打包的,包括polyfill zepto detect event ajax form fx fx_methods data assets selector touch 共11个模块。过段时间zepto入门了再写个基于zepto的无缝轮播插件。毕竟移动端上zepto更适合一点,起码在中国目前的移动网络下。