Unslider Web前端框架之图片轮播

前端框架,前端组件,前端库,都是一个意思,能看源码。

最近做H5小游戏,用到了图片轮播的组件,而且要求支持移动端触屏滑动。一开始用的是nivo slider,但是对大小不一样的图不支持box 的参数设置。unslider,满足了需求。

Unslider--入门篇

背景:因工作需求,需要完成一个图片轮播效果,因博主不是专业的前端开发人员,so google之,经过挑选最终选择使用Unslider插件完成工作。

一、Unslider插件介绍

unslider插件是一个超小的jQuery轮播(slider)插件,大小不到3k,源码托管在GitHub上,是一个开源项目。

1、跨浏览器

Unslider已经在所有最新的浏览器上测试过了,并能对那些老旧的浏览器也能做出很好的降级处理。(PS:博主亲测,在IE8上使用正常

2、支持键盘导航(没错,你没看错,就是键盘上的左右键,很炫,有木有!!)

3、自动调整高度

4、支持响应式布局(不懂的链接在此,自戳:响应式布局)

说了这么多特色了,看一下效果眼见为实吧,链接:http://www.bootcss.com/p/unslider/

看了效果,有没有感觉博主的好多文是copy来的,╮(╯▽╰)╭木办法,博主水平有限,只能边学边做笔记给大家分享了,多多包涵啦。( ̄︶ ̄)↗

二、如何使用Unslider

1、引入jQuery和Unslider

使用Unslider,你需要在页面中引入Unslider和jquery脚本,jQuery版本不限,建议在版本1.8+(博主亲测使用1.8版本的jQuery.js可正常使用Unslider脚本)。

如何验证页面已引入jQuery脚本,按F12,在控制台中输入!!window.jQuery,若返回true,则说明页面中已引入jQuery脚本。

引入jQuery、Unslider脚本,页面代码如下:

1 <script src="//code.jquery.com/jquery-latest.min.js"></script>
2 <script src="//unslider.com/unslider.js"></script>
View Code

2、准备HTML代码

div+ul li(无序列表),完美解决,无需额外的html标签!为了简洁我们的例子只写三个li,上代码!

 1  <div class="banner">
 2       <ul>
 3           <li style="100%;height:50px;">
 4               <h1>This is a slide.</h1>
 5           </li>
 6           <li style="100%;height:50px;">
 7               <h2>This is another slide.</h2>
 8           </li>
 9           <li style="100%;height:50px;">
10              <h3>This is a final slide.</h3>
11          </li>
12       </ul>
13 </div>

PS:css样式以及h1、h2、h3标签的使用,只是为了能更好的展现出页面切换的效果,不必深究。

3、增加Css样式,使页面效果更漂亮

Unslider插件没有提供一个标准的CSS样式,你可以尽情操作每张幻灯片(每个li标签内存放一张幻灯片)的Css样式,自由度之大可以想象。

 1 .banner { 
 2     position: relative; 
 3     overflow: auto; 
 4 }
 5 .banner li {
 6      list-style: none; 
 7 }
 8 .banner ul li {
 9      float: left; 
10 }

  

4、使用unslider插件

 1 $(function() {
 2   var slidey = $('.banner').unslider({
 3     speed: 500,               
 4   delay: 3000,            
 5   complete: function() {}, 
 6   keys: true,             
 7   dots: true,              
 8   fluid: false
 9 });
10   data = slidey.data('unslider'); 
11   data.move(2, function() {}); 
12 });

二、源码分析

[javascript] view plaincopy
 
 
  1 /** 
  2  *   Unslider by @idiot and @damirfoy 
  3  *   Contributors: 
  4  *   - @ShamoX 
  5  * 
  6  */  
  7   
  8 (function($, f) {  
  9     var Unslider = function() {  
 10         //  克隆对象  
 11         var _ = this;  
 12   
 13         //  设置一些默认参数  
 14         _.o = {  
 15             speed: 500,     // 动画过渡的速度(毫秒),如果不需要过渡效果就设置为false  
 16             delay: 3000,    // 每张幻灯片的间隔时间(毫秒), 如果不是自动播放就设置为false  
 17             init: 0,        // 初始化延迟时间(毫秒),如果不需要延迟就设置为false  
 18             pause: !f,      // 当鼠标指针浮动在当前区域内时是否暂停自动播放  
 19             loop: !f,       // 是否无尽循环播放  
 20             keys: f,        // 是否开启键盘导航  
 21             dots: f,        // 是否显示导航点  
 22             arrows: f,      // 是否显示向前和向后的箭头  
 23             prev: '←',     // 向前按钮中的显示文字(或html片段)  
 24             next: '→',     // 向后......  
 25             fluid: f,       // 是否宽度自适应  
 26             starting: f,    // 在每个动画前调用的函数  
 27             complete: f,    // 在每个动画之后调用的函数  
 28             items: '>ul',   // 幻灯片的容器选择器  
 29             item: '>li',    // 需要滚动的选择器  
 30             easing: 'swing',// 动画的缓动函数(easing function)  
 31             autoplay: true  // 是否允许自动播放  
 32         };  
 33   
 34         _.init = function(el, o) {  
 35             //  将我们在外部调用时设置的参数覆盖掉默认参数  
 36             _.o = $.extend(_.o, o);  
 37   
 38             _.el = el;  
 39             _.ul = el.find(_.o.items);//返回ul元素集合  
 40             _.max = [el.outerWidth() | 0, el.outerHeight() | 0];//保存一下幻灯片div容器的宽和高  
 41             _.li = _.ul.find(_.o.item).each(function(index) {  
 42                 var me = $(this),  
 43                     width = me.outerWidth(),  
 44                     height = me.outerHeight();  
 45   
 46                 //  记录最大幻灯片的宽高  
 47                 if (width > _.max[0]) _.max[0] = width;  
 48                 if (height > _.max[1]) _.max[1] = height;  
 49             });  
 50   
 51   
 52             //  申请一些临时变量  
 53             var o = _.o,  
 54                 ul = _.ul,  
 55                 li = _.li,  
 56                 len = li.length;//li元素个数  
 57   
 58             //  当前索引,或者叫页码更容易理解吧,源代码中写了“Current indeed”,应该是“index”吧  
 59             _.i = 0;  
 60   
 61             //  设置幻灯片div容器的样式,高度初始化为第一个li的高度  
 62             el.css({ _.max[0], height: li.first().outerHeight(), overflow: 'hidden'});  
 63   
 64             //  设置ul元素的位置和宽度,宽度的公式是(li元素的个数乘以100)%,我的例子中就是300%  
 65             ul.css({position: 'relative', left: 0,  (len * 100) + '%'});  
 66             if(o.fluid) {  
 67                 li.css({'float': 'left',  (100 / len) + '%'});//自适应宽度时,li元素的宽度就是把ul的宽度平均分成len份  
 68             } else {  
 69                 li.css({'float': 'left',  (_.max[0]) + 'px'});//不是自适应时,li元素的宽度是最大的幻灯片的宽度  
 70             }  
 71   
 72             //  在init毫秒后开启自动播放  
 73             o.autoplay && setTimeout(function() {  
 74                 if (o.delay | 0) {  
 75                     _.play();  
 76   
 77                     if (o.pause) {  
 78                         el.on('mouseover mouseout', function(e) {  
 79                             _.stop();//鼠标经过时暂停  
 80                             e.type == 'mouseout' && _.play();//鼠标离开时播放  
 81                         });  
 82                     };  
 83                 };  
 84             }, o.init | 0);  
 85   
 86             //  键盘事件处理  
 87             if (o.keys) {  
 88                 $(document).keydown(function(e) {  
 89                     var key = e.which;  
 90   
 91                     if (key == 37)  
 92                         _.prev(); // 左箭头按键  
 93                     else if (key == 39)  
 94                         _.next(); // 右箭头按键  
 95                     else if (key == 27)  
 96                         _.stop(); // Esc  
 97                 });  
 98             };  
 99   
100             //  显示导航点  
101             o.dots && nav('dot');  
102   
103             //  显示箭头  
104             o.arrows && nav('arrow');  
105   
106             //  使幻灯片div容器宽度自适应  
107             if (o.fluid) {  
108                 $(window).resize(function() {  
109                     _.r && clearTimeout(_.r);  
110   
111                     _.r = setTimeout(function() {  
112                         var styl = {height: li.eq(_.i).outerHeight()},  
113                             width = el.outerWidth();  
114   
115                         ul.css(styl);  
116                         //这一串真是绕,其实就是计算div占父窗口的宽度原始比例,然后记录到styl中  
117                         styl['width'] = Math.min(Math.round((width / el.parent().width()) * 100), 100) + '%';  
118                         el.css(styl);//重新设置幻灯片div容器的宽度为比例而不是像素值,这样就能达到自适应的目的了  
119                         li.css({  width + 'px' });//设置li的绝对宽度,以防因div被自适应了而挤压或拉伸了li造成内容扭曲(如有误请大神指教)  
120                     }, 50);//每次父窗口改变大小时,幻灯片div容器延迟50毫秒后再跟着自适应大小,请大神告诉我这样做的目的仅仅是为了效果更自然么  
121                 }).resize();//强制执行resize事件,使得自适应特性在最开始时就被设置好了  
122             };  
123   
124             //  自定义move事件,这一段不太懂,求大神指点  
125             if ($.event.special['move'] || $.Event('move')) {  
126                 //  为幻灯片div元素绑定movestart、move、moveend事件  
127                 el.on('movestart', function(e) {  
128                     if ((e.distX > e.distY && e.distX < -e.distY) || (e.distX < e.distY && e.distX > -e.distY)) {  
129                         e.preventDefault();//鼠标位置不在当前区域时取消事件的默认动作(我猜的,关键是不知道distX这几个的准确含义)  
130                     }else{  
131                         el.data("left", _.ul.offset().left / el.width() * 100);  
132                     }  
133                 }).on('move', function(e) {  
134                         var left = 100 * e.distX / el.width();  
135                         var leftDelta = 100 * e.deltaX / el.width();  
136                         _.ul[0].style.left = parseInt(_.ul[0].style.left.replace("%", ""))+leftDelta+"%";  
137   
138                         _.ul.data("left", left);  
139                     }).on('moveend', function(e) {  
140                         var left = _.ul.data("left");//  
141                         if (Math.abs(left) > 30){  
142                             var i = left > 0 ? _.i-1 : _.i+1;  
143                             if (i < 0 || i >= len) i = _.i;  
144                             _.to(i);  
145                         }else{  
146                             _.to(_.i);  
147                         }  
148                     });  
149             };  
150   
151             return _;  
152         };  
153   
154         //  播放指定索引的幻灯片  
155         _.to = function(index, callback) {  
156             if (_.t) {  
157                 _.stop();  
158                 _.play();  
159             }  
160             var o = _.o,  
161                 el = _.el,  
162                 ul = _.ul,  
163                 li = _.li,  
164                 current = _.i,  
165                 target = li.eq(index);  
166             //在动画之前执行的函数,我的例子里都没有,可以忽略它们  
167             $.isFunction(o.starting) && !callback && o.starting(el, li.eq(current));  
168   
169             //  如果(一张幻灯片也没有或者索引无效),并且不是循环播放,就啥也不做,我觉得这样不好,因为to这个函数就只能在循环播放状态下工作了  
170             if ((!target.length || index < 0) && o.loop == f) return;  
171   
172             //  检查索引是否有效,超出时设置为0,即第一张幻灯片  
173             if (!target.length) index = 0;  
174             if (index < 0) index = li.length - 1;//索引负数时设置为最后一张幻灯片  
175             target = li.eq(index);//获取目标元素  
176   
177             var speed = callback ? 5 : o.speed | 0,//执行回调函数后返回的是真则speed设为5,如果没有回调函数或返回假则设置为o.speed  
178                 easing = o.easing,  
179                 obj = {height: target.outerHeight()};  
180   
181             if (!ul.queue('fx').length) {//确保没有为ul元素添加函数队列,应该是为了防止上一次动作还没有完成吧  
182                 //  设置对应导航点的高亮  
183                 el.find('.dot').eq(index).addClass('active').siblings().removeClass('active');  
184                 //  改变幻灯片div容器的高度为目标元素的高度,并把ul的位置向左移动(index*100%),使目标元素正好在幻灯片div容器区域  
185                 el.animate(obj, speed, easing) && ul.animate($.extend({left: '-' + index + '00%'}, obj), speed, easing, function(data) {  
186                     _.i = index;//移动结束之后更新一下当前索引  
187                     //动画结束之后执行的函数,我的例子中也没有,忽略它们  
188                     $.isFunction(o.complete) && !callback && o.complete(el, target);  
189                 });  
190             };  
191         };  
192   
193         //  每隔delay毫秒自动播放  
194         _.play = function() {  
195             _.t = setInterval(function() {  
196                 _.to(_.i + 1);//这里就加了1个索引号,具体的处理都封装在了to方法中  
197             }, _.o.delay | 0);  
198         };  
199   
200         //  停止自动播放  
201         _.stop = function() {  
202             _.t = clearInterval(_.t);  
203             return _;  
204         };  
205   
206         //  向后翻一张  
207         _.next = function() {  
208             return _.stop().to(_.i + 1);  
209         };  
210         //  向前翻一张  
211         _.prev = function() {  
212             return _.stop().to(_.i - 1);  
213         };  
214   
215         //  创建导航点和箭头  
216         function nav(name, html) {  
217             if (name == 'dot') {  
218                 html = '<ol class="dots">';  
219                 $.each(_.li, function(index) {  
220                     html += '<li class="' + (index == _.i ? name + ' active' : name) + '">' + ++index + '</li>';  
221                 });  
222                 html += '</ol>';  
223                 /*整理一下,在我的例子中就是这副摸样 
224                   <ol class="dots">            
225                   <li class="dot active">0</li> 
226                   <li class="dot">1</li> 
227                   <li class="dot">2</li> 
228                   </ol> 
229                 */  
230             } else {  
231                 html = '<div class="';  
232                 html = html + name + 's">' + html + name + ' prev">' + _.o.prev + '</div>' + html + name + ' next">' + _.o.next + '</div></div>';  
233                 /*也整理一下 
234                   <div class="arrows"> 
235                     <div class="arrow prev">←</div> 
236                     <div class="arrow next">→</div> 
237                   </div> 
238                 */  
239             };  
240             //先给幻灯片div容器元素加上has-dots或arrows的class,再把上面组织好的元素追加为子元素,并给该子元素添加click事件处理函数  
241             _.el.addClass('has-' + name + 's').append(html).find('.' + name).click(function() {  
242                 var me = $(this);  
243                 me.hasClass('dot') ? _.stop().to(me.index()) : me.hasClass('prev') ? _.prev() : _.next();  
244             });  
245         };  
246     };  
247   
248     //  将unslider方法扩展到jQuery对象,使任意jQuery对象都能够直接访问该方法,就像上面那样:$('.banner').unslider();  
249     $.fn.unslider = function(o) {  
250         var len = this.length;  
251   
252         //  遍历li元素集  
253         return this.each(function(index) {  
254             var me = $(this),  
255                 key = 'unslider' + (len > 1 ? '-' + ++index : ''),  
256                 instance = (new Unslider).init(me, o);  
257   
258             //  给div元素添加数据  
259             me.data(key, instance).data('key', key);  
260         });  
261     };  
262   
263     Unslider.version = "1.0.0";  
264 })(jQuery, false);  

三、定制自己需要的幻灯片

终于看完大部分了。好了,通过源码至少我知道了该怎样去控制外观,现在我要动手啦,心里有点小激动呢~

我选择Unslider是因为它是如此纯粹,正如我想要的那样,啥也可以不要,只要能自动循环播放、用导航点控制翻页就满足我的要求了。

因为默认就是自动循环播放的,所以我只要设置一个显示导航点的参数即可,然后锦上添花也支持一下响应式吧:

[javascript] view plaincopy
 
1 $(function() {  
2     $('.banner').unslider({  
3         dots: true,               //  显示导航点  
4         fluid: true               //  支持响应式设计  
5     });  
6 });  


通过源码我们知道unslider为我们写好了导航点的文档结构、并取好了类名,但并没有设置样式,所以只是传个参数是木有用滴,要自己写样式才能看见那些可爱的点点:

[javascript] view plaincopy
 
 
 1 *{margin: 0;padding: 0;}  
 2 .banner { position: relative; top:0;overflow: auto; }  
 3 .banner li { list-style: none; }  
 4 .banner ul li { float: left; }  
 5 .dots{66px;position:absolute;bottom:10px;left:50%;margin-left:-27px;}  
 6 .dot{  
 7     display:inline-block;  
 8      10px;  
 9     height: 10px;  
10     font-size: 0px;  
11     line-height: 0px;  
12     margin-right: 12px;  
13     cursor: pointer;  
14     background-color: #ffffff;  
15     border-radius: 8px;  
16 }  
17 .dot.active{background-color: #cce8cf;}  

大功告成!

四、总结

对jquery的事件机制还不熟悉,遇到自定义事件啥的就犯晕了,这块知识还要多加学习。

摘自:http://blog.csdn.net/u011411283/article/details/47066481

感谢分享!

原文地址:https://www.cnblogs.com/wbq-wyw/p/7017611.html