響應式輪播unslider使用方法2


一、如何使用

第1步:導入類庫

Unslider是基於jQuery,自然要先將Jquery庫導入

 

[javascript]  view plain copy
 print?
  1. <script src="http://code.jquery.com/jquery-latest.min.js"></script>  
  2. <script src="http://unslider.com/unslider.js"></script>  


第2步:寫HTML結構,即幻燈片列表

 

 

[html]  view plain copy
 print?
  1. <div class="banner">  
  2.     <ul>  
  3.         <li style="background:url(1.jpg)">first slide.</li>  
  4.         <li style="background:url(2.jpg)">second slide.</li>  
  5.         <li style="background:url(3.jpg)">third slide.</li>  
  6.     </ul>  
  7. </div>  

 

第3步:添加樣式,這里先不管漂亮,只放官網上說必須有的骨架

 

[css]  view plain copy
 print?
  1. .banner { position: relative; overflow: auto; }  
  2. .banner li { list-style: none; }  
  3. .banner ul li { float: left; }  

 

 

第4步:調用unslider()方法讓幻燈片列表滾動起來,參數就先默認吧

 

 

[javascript]  view plain copy
 print?
  1. $(function() {  
  2.     $('.banner').unslider();  
  3. });  


好了,到這里幻燈片就如預期滾動起來了。但是不美觀,為了更加靈活定制自己想要的效果,我要潛入源代碼瞧一瞧。

二、源碼分析

 

 

[javascript]  view plain copy
 print?
  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({width: _.max[0], height: li.first().outerHeight(), overflow: 'hidden'});  
  63.   
  64.             //  設置ul元素的位置和寬度,寬度的公式是(li元素的個數乘以100)%,我的例子中就是300%  
  65.             ul.css({position: 'relative', left: 0, width: (len * 100) + '%'});  
  66.             if(o.fluid) {  
  67.                 li.css({'float': 'left', width: (100 / len) + '%'});//自適應寬度時,li元素的寬度就是把ul的寬度平均分成len份  
  68.             } else {  
  69.                 li.css({'float': 'left', width: (_.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: 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 plain copy
 print?
  1. $(function() {  
  2.     $('.banner').unslider({  
  3.         dots: true,               //  顯示導航點  
  4.         fluid: true               //  支持響應式設計  
  5.     });  
  6. });  


通過源碼我們知道unslider為我們寫好了導航點的文檔結構、並取好了類名,但並沒有設置樣式,所以只是傳個參數是木有用滴,要自己寫樣式才能看見那些可愛的點點:

 

 

[javascript]  view plain copy
 print?
  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{width:66px;position:absolute;bottom:10px;left:50%;margin-left:-27px;}  
  6. .dot{  
  7.     display:inline-block;  
  8.     width: 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的事件機制還不熟悉,遇到自定義事件啥的就犯暈了,這塊知識還要多加學習。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM