DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> JavaScript入門知識 >> 關於JavaScript >> 值得分享的JavaScript實現圖片輪播組件
值得分享的JavaScript實現圖片輪播組件
編輯:關於JavaScript     

本文實例為大家分享了JavaScript實現圖片輪播組件的使用方法,供大家參考,具體內容如下

效果:

自動循環播放圖片,下方有按鈕可以切換到對應圖片。
添加一個動畫來實現圖片切換。
鼠標停在圖片上時,輪播停止,出現左右兩個箭頭,點擊可以切換圖片。
鼠標移開圖片區域時,從當前位置繼續輪播。
提供一個接口,可以設置輪播方向,是否循環,間隔時間。
點擊查看demo

對HTML、CSS的要求:

<div class="carousel-box">
 <div class="carousel">
  <ul class="clearfix" >
   <li><img src="img/carousel01.jpg" alt=""></li>
   <li><img src="img/carousel02.jpg" alt=""></li>
   <li><img src="img/carousel03.jpg" alt=""></li>
   <li><img src="img/carousel04.jpg" alt=""></li>
   <li><img src="img/carousel05.jpg" alt=""></li>
   <li><img src="img/carousel06.jpg" alt=""></li>
  </ul>
 </div>
</div>

*必須是兩個盒子嵌套,最裡面的盒子需要有一個ul,圖片需要被包含在li裡。
*可以更改類名,同時將css文件中的相應類名替換即可。配置組件時傳入正確的DOM元素即可。
*不限制圖片寬度和數量,在css文件中更改數值即可。

/*需要更改的值*/
.carousel img{ 
 width: 600px;
 height: 400px;
}
.carousel,
.carousel-box {
 width: 600px; /*單張圖片寬度*/
 height: 400px; /*單張圖片高度*/
}
.carousel ul{
 width: 3600px; /*單張圖片寬度x圖片數量*/
}

原理:

將所有圖片橫向排列,最外層容器和包裹容器設置overflow:hidden。最外層容器用於按鈕和箭頭的定位。利用包裹容器的scrollLeft屬性控制顯示哪張圖片。

思路:

想要實現這些功能,應該有以下一些方法:

1.圖片切換函數。接受一個參數,表示滾動方向。調用緩動函數切換圖片。調用切換按鈕圖標函數點亮相應的按鈕。

2.緩動函數。

3.點亮按鈕函數。

4.初始化函數。用於綁定事件,創建按鈕和箭頭,初始化最初位置。

5.創建箭頭函數。

6.創建按鈕函數。

7.開始輪播函數。

8.輪播函數。

9.停止函數。用於停止輪播。

還有一些公用方法

$():選擇DOM元素。

addClass(ele,"className"):給元素添加類名。

removeClass(ele,"className"):移除元素的類名。

$.add(ele,"type",fun):給一個DOM節點綁定事件。

getCSS(ele,"prop"):獲取元素相應屬性的值。

$.delegateTag("selector","tagName","type",fun):事件代理。

實現:

假設有6張圖片,每張圖片寬度為600px。按照功能的獨立性來完成:

1.緩動函數  liner
緩動函數的作用是一點一點的改變目標元素的屬性值,直到達到目標值。使用它的元素可能是水平輪播的圖片,也可能是垂直輪播的圖片,也可能是一個想從頁面左端到達頁面右端的小盒子。所以它應該接收四個參數(目標元素,要改變的屬性值,目標值,移動次數)。

liner=function(ele,prop,next,num){
 var speed=(next-ele[prop])/num,
  i=0;
 (function(){
  ele[prop]+=speed;
  i++;
  if (i<num) {
   setTimeout(arguments.callee,30);
  }
 })(); 
},

2.點亮按鈕函數  light
點亮按鈕本質上就是給按鈕添加一個active類,熄滅按鈕就是給按鈕移除active類。

那麼如何知道當前按鈕是哪一個呢?

最簡單的方法是直接獲取,所以可以給每個按鈕添加一個index屬性,當需要點亮按鈕時,將要點亮的按鈕的index傳給這個函數即可。

那麼如何知道要熄滅的按鈕是哪一個呢?

最簡單的方法也是直接獲取,所以可以在作用域鏈末端添加一個變量active,記住當前亮著的按鈕,這個函數直接將他熄滅就可以了。

light=function(index){
 removeClass(active,"active");
 active=$(this.wrapSelec+" "+"[index="+index+"]");
 addClass(active,"active");
}

3.圖片切換函數  go
需要計算出下一個scrollLeft的值:

如果是向左移動的話,scrollLeft應該-600,如果已經是0,就切換為3000.所以是ele.scrollLeft===0?width*(len-1):ele.scrollLeft-width;

如果是向右移動的話,scrollLeft應該+600,即0——>600,600——>1200,...,3000——>0。這裡可以像上面那樣用判斷,也可以用一個公式next=(cur+distance)%(distance*num)。即(ele.scrollLeft+width)%(width*len)

需要獲得下一個要被點亮的按鈕的index:

和計算scrollLeft的思路一樣,往左移動:index===0? len-1:index-1; 往右移動:(index+1)%len

go=function(dire){
 var index=active.getAttribute("index")-0,
  nextIndex,
  nextPosition;
 if (dire==="next") {
  nextIndex=(index+1)%len;
  nextPosition=(ele.scrollLeft+width)%(width*len);
 }else{
  nextIndex=index===0? len-1:index-1,
  nextPosition=ele.scrollLeft===0?width*len:ele.scrollLeft-width;
 }
 light(nextIndex);
 animate.liner(ele,"scrollLeft",nextPosition); 
}

其中的len(圖片總數)、width(圖片寬度)、ele(包裹容器)也會被其他函數訪問,所以也添加到作用域鏈末端。

len=ele.getElementsByTagName("img").length

width=parseInt(getCSS(ele.getElementsByTagName("img")[0],"width");

ele=$(eleSelec),eleSelec是包裹容器的selector,比如.carousel

4.創建箭頭函數 createArrow
創建一個向左的箭頭,綁定事件處理函數,用於向左移動。創建一個向右的箭頭,綁定事件處理函數,用於向右移動。

createArrow=function(){
 var prev=document.createElement("div"),
  next=document.createElement("div");
 prev.appendChild(document.createTextNode("<"));
 next.appendChild(document.createTextNode(">"));
 prev.className="arrow prev";
 next.className="arrow next"; 
 container.appendChild(prev);
 container.appendChild(next);
 addClass(container,"hide");
 $.add(next,"click",function(){
  go("next");
 });
 $.add(prev,"click",function(){
  go("prev");
 });
}

container代表最外層容器,也會被其他函數訪問,所以也添加到作用域鏈末端。

container=$(wrapSelec),wrapSelec是最外層容器的selector,比如.carousel-box

5.創建按鈕函數 createBtn
給每個按鈕添加一個index用於點亮和熄滅,給按鈕組添加一個類名用於設置樣式和獲取它:

createBtn=function(){
 var div=document.createElement("div"),
  btns='';
 for(var i=0;i<len;i++){
  btns+='<a href="#" index="'+i+'"></a>';
 }
 div.innerHTML=btns;
 addClass(div,"carousel-btn");
 container.appendChild(div);
}

6.輪播函數
根據要求(順時針、逆時針)判斷要調用go("prev")還是go("next")。

如果要求循環,則再次調用自己。如果不循環,則在輪播一輪後停止。

所以這裡需要一個變量來判斷方向,一個變量來判斷是否循環,一個變量來計數。

所以又有四個變量被加到作用域鏈末端。direction、loop、count、begin用於清除定時器。

circle=function(){
 count++;
 if (loop||count<len) {
  if (direction==="forward") {
   go("next");
  }else{
   go("prev");
  }
 }
 begin=setTimeout(arguments.callee,t);
}

7.停止函數 stop

stop=function(){
 clearTimeout(begin);
}

8.初始化函數 init
如果是第一次使用輪播,則創建按鈕和箭頭,並給按鈕綁定click事件處理程序(獲取點擊的按扭index點亮它,切換到相應圖片),然後根據順時針或逆時針來展示相應的圖片和按鈕。

所以這裡又需要有一個變量加在作用域鏈末端,用於表示是否已經初始化。

init=function(){
 createBtn();
 createArrow();
 $.delegateTag(wrapSelec+" "+".carousel-btn","a","click",function(e,target){
  $.prevent(e);
  light(target.getAttribute("index"));
  animate.liner(ele,"scrollLeft",target.getAttribute("index")*width);
 });
 $.add(container,"mouseenter",function(){
  stop();
  removeClass(container,"hide");
 });
 $.add(container,"mouseleave",function(){
  addClass(container,"hide");
  begin=setTimeout(circle,t); 
 });if (direction==="forward") {
  light(0);
 }else{
  light(len-1);
  ele.scrollLeft=width*(len-1);
 }
 haveStart=true;
}

9.開始輪播函數 start

這個函數當做接口,用於控制輪播方向,間隔時間,和是否循環。計數器歸零。

因為可能重復的開始輪播,所以每次開始之前都需要清除定時器。

start=function(dir,th,lo){
 stop();
 count=0;
 direction=dir;
 t=th*1000;
 loop=lo;
 if (!haveStart) {
  init();
 }
 begin=setTimeout(circle,t);
}

到這裡,所有需要用到的函數已經寫完了,如果把這些函數和那些需要的變量扔到一個函數裡,把外層容器盒包裹容器的類名或ID傳給它,這個函數返回一個包含start和stop方法的對象,這個組件就可以使用了。

但是有一個問題,這個函數只有一個,也就是說,一個頁面只能有一個輪播實例。所以,如果想要一個頁面能有兩個輪播實例都用這個組件的話,就不能把它們扔到一個函數裡。那麼就只能放到對象裡。每個對象有自己的變量,他們共用一組方法。

那麼,這些變量就不能直接訪問了,需要通過對象的屬性訪問,即this。

這時候就會出現問題,this是會指向調用它的那個環境,所以當那些變量在事件處理程序中,或是在定時器中被訪問的時候,就不能用this,而是要創建一個閉包。

即,在能獲取到this時,將this賦值給一個變量,然後在事件處理程序或是定時器中訪問這個變量,就會獲取到正確的對象。

以init函數為例來改裝:

carouselProto.init=function(){
 var that=this;
 this.createBtn();
 this.createArrow();
 $.delegateTag(this.wrapSelec+" "+".carousel-btn","a","click",function(e,target){
  $.prevent(e);
  that.light(target.getAttribute("index"));
  animate.liner(that.ele,"scrollLeft",target.getAttribute("index")*that.width);
 });
 $.add(this.container,"mouseenter",function(){
  that.stop();
  removeClass(that.container,"hide");
 });
 $.add(this.container,"mouseleave",function(){
  addClass(that.container,"hide");
  that.begin=setTimeout(function(){
   that.circle();
  },that.t); 
 });if (this.direction==="forward") {
  this.light(0);
 }else{
  this.light(this.len-1);
  this.ele.scrollLeft=this.width*(this.len-1);
 }
 this.haveStart=true;
};

這樣改裝完之後,就可以創建實例了,每個實例都會有自己的屬性用於記錄狀態,他們都共用原型中的方法。

如果采用原型繼承的方式的話,可以創建一個對象作為實例的原型對象,然後創建一個函數來生產實例:

var carouselProto={};

//把上面那些方法給這個對象
carouselProto.light=...
carouselProto.go=...
carouselProto.stop=...

//創建實例對象函數
var carousel=function(eleSelec,wrapSelec){
 var that=Object.create(carouselProto);
 that.wrapSelec=wrapSelec;
 that.ele=$(eleSelec);
 that.container=$(wrapSelec);
 that.len=that.ele.getElementsByTagName("img").length;
 that.width=parseInt(getCSS(that.ele.getElementsByTagName("img")[0],"width"));
 return that;
}

//創建實例,使用組件
var carousel1=carousel(".carousel",".carousel-box");
  carousel1.start("forward",3,true);
var carousel2=carousel(".carousel2",".carousel-box2");
  carousel2.start("backward",2,true);

性能優化:

1.當點擊的按鈕剛好是當前被點亮的按鈕時,依然會調用一次light和animate.liner。所以可以添加一個判斷語句,如果點擊的按鈕剛好是正確的,就不要執行下面的了。

$.delegateTag(this.wrapSelec+" "+".carousel-btn","a","click",function(e,target){
 $.prevent(e);
 var index=target.getAttribute("index");
 if (index===that.active.getAttribute("index")) {
  return
 }
 that.light(index);
 animate.liner(that.ele,"scrollLeft",target.getAttribute("index")*that.width);
});

2.當圖片切換的時候,緩動動畫正在執行。如果在緩動動畫還沒執行完時就點擊按鈕或者箭頭,就會進入下一次動畫,於是就會出現混亂,圖片錯位。性能也會受到影響。為了防止這種情況發生,可以使用一個變量,用於記錄緩動動畫是否正在執行,沒有執行的話點擊按鈕或箭頭才會執行函數。

liner=function(ele,prop,next){
 var speed=(next-ele[prop])/10,
  i=0;
 ele.animating=true;
 (function(){
  ele[prop]+=speed;
  i++;
  if (i<10) {
   setTimeout(arguments.callee,60);
  }else{
   ele.animating=false;
  }
 })(); 
}
if (!this.ele.animating) {
 this.light(nextIndex);
  animate.liner(this.ele,"scrollLeft",nextPosition);
}

點擊查看源碼 

參考資源:

慕課網——焦點圖輪播特效
《JavaScript:The Good Parts》

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持。

XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved