一步一步教你寫淡入淡出帶注釋的圖片輪播插件(二)
更新時間:2010年10月11日 21:49:35 作者:
開始之前,還是說說前文提到的關(guān)于把所有函數(shù)都寫在一個閉包內(nèi)的優(yōu)化問題。前文也提到了,因為我們在初始化的時候要調(diào)用的只是init,所以可以只把init寫入閉包,其他功能函數(shù)作為init的原型繼承方法來調(diào)用。
接上一篇,現(xiàn)在進行第二部分。
開始之前,還是說說前文提到的關(guān)于把所有函數(shù)都寫在一個閉包內(nèi)的優(yōu)化問題。前文也提到了,因為我們在初始化的時候要調(diào)用的只是init,所以可以只把init寫入閉包,其他功能函數(shù)作為init的原型繼承方法來調(diào)用。所以前文的代碼其實可以這樣改寫:
var Hongru={};
function H$(id){return document.getElementById(id)}
function H$$(c,p){return p.getElementsByTagName(c)}
Hongru.fader = function(){
function init(options){ //options參數(shù):id(必選):圖片列表父標(biāo)簽id;auto(可選):自動運行時間;index(可選):開始的運行的圖片序號
var wp = H$(options.id), // 獲取圖片列表父元素
ul = H$$('ul',wp)[0], // 獲取
li = this.li = H$$('li',ul);
this.a = options.auto?options.auto:2; //自動運行間隔
this.index = options.position?options.position:0; //開始運行的圖片序號(從0開始)
this.l = li.length;
this.cur = this.z = 0; //當(dāng)前顯示的圖片序號&&z-index變量
this.pos(this.index); //變換函數(shù)
}
init.prototype = {
auto:function(){
this.li.a = setInterval(new Function('Hongru.fader.move(1)'),this.a*1000);
},
move:function(i){//參數(shù)i有兩種選擇,1和-1,1代表運行到下一張,-1代表運行到上一張
var n = this.cur+i;
var m = i==1?n==this.l?0:n:n<0?this.l-1:n; //下一張或上一張的序號(注意三元選擇符的運用)
this.pos(m); //變換到上一張或下一張
},
pos:function(i){
clearInterval(this.li.a);
this.z++;
this.li[i].style.zIndex = this.z; //每次讓下一張圖片z-index加一
this.cur = i; //綁定當(dāng)前顯示圖片的正確序號
this.auto(); //自動運行
}
}
return {init:init}
}();
但是這樣其實是有問題的,不知道大家發(fā)現(xiàn)沒有,如果這樣改寫的話,在auto函數(shù)里就不能再調(diào)用‘Hongru.fader.move()'了,這是沒定義的,那有人會說,既然是init的原型繼承,那就調(diào)用'Hongru.fader.init.move()'不就對了嗎?其實也不對,我在以前的文章中就討論過這個問題http://www.cnblogs.com/hongru/archive/2010/10/09/1846636.html;init在沒有實例化之前是訪問不到它的prototype的,所以我們在這樣做的時候要注意兩個問題,
一個是初始化的時候要用new關(guān)鍵字對init實例化。
另外一個是在代碼內(nèi)部調(diào)用它的原型方法時也要通過我們實例化后的對象來調(diào)用,舉個例子,比如我們對上面的代碼初始化的時候應(yīng)該是這樣的
var newFader = new Hongru.fader.init({ //這個new很重要
id:'fader'
});
如果我們在代碼里要調(diào)用init的方法要通過我們新建的實例化對象newFader來調(diào)用,比如在上面的auto函數(shù)里要調(diào)用init的move方法的話,就直接調(diào)用'newFader.move()',這樣才行。
可是這樣還有個小問題,就是必須要保證實例化的變量名和代碼中調(diào)用的一致,那么如果我改了我的初始化對象的名字,比如用newFader1,那么我還得去改源碼,這樣肯定是不行的,所以有個小技巧,就是在init里面多傳一個參數(shù),自己在做初始化的時候讓變量名和參數(shù)一致,然后在源碼里我們通過參數(shù)來調(diào)用。這樣問題就圓滿的解決了。
(ps:代碼里之所以使用new Function的原因也是因為這樣能沖破作用域鏈,這也是保證我們能這樣架構(gòu)我們代碼的條件之一。)
綜上:之前的代碼應(yīng)該這樣優(yōu)化:
var Hongru={};
function H$(id){return document.getElementById(id)}
function H$$(c,p){return p.getElementsByTagName(c)}
Hongru.fader = function(){
function init(anthor,options){this.anthor=anthor; this.init(options);}
init.prototype = {
init:function(options){ //options參數(shù):id(必選):圖片列表父標(biāo)簽id;auto(可選):自動運行時間;index(可選):開始的運行的圖片序號
var wp = H$(options.id), // 獲取圖片列表父元素
ul = H$$('ul',wp)[0], // 獲取
li = this.li = H$$('li',ul);
this.a = options.auto?options.auto:2; //自動運行間隔
this.index = options.position?options.position:0; //開始運行的圖片序號(從0開始)
this.l = li.length;
this.cur = this.z = 0; //當(dāng)前顯示的圖片序號&&z-index變量
this.pos(this.index); //變換函數(shù)
},
auto:function(){
this.li.a = setInterval(new Function(this.anthor+'.move(1)'),this.a*1000);
},
move:function(i){//參數(shù)i有兩種選擇,1和-1,1代表運行到下一張,-1代表運行到上一張
var n = this.cur+i;
var m = i==1?n==this.l?0:n:n<0?this.l-1:n; //下一張或上一張的序號(注意三元選擇符的運用)
this.pos(m); //變換到上一張或下一張
},
pos:function(i){
clearInterval(this.li.a);
this.z++;
this.li[i].style.zIndex = this.z; //每次讓下一張圖片z-index加一
this.cur = i; //綁定當(dāng)前顯示圖片的正確序號
this.auto(); //自動運行
}
}
return {init:init}
}();
初始化時應(yīng)該這樣:
var fader = new Hongru.fader.init('fader',{ //保證第一個參數(shù)和變量名一致
id:'fader'
});
好了,代碼的優(yōu)化方案到此結(jié)束。下面是第二部分效果的實現(xiàn):淡入淡出的效果
其實有了上面良好的代碼結(jié)構(gòu)和邏輯的話,加入淡入淡出效果是比較容易的,思路很簡單,在變化之前讓圖片透明,然后通過計時器讓透明度漸漸增加。只不過這里面有幾個邊界的判斷是比較重要的。同時透明度改變在ie和非ie下要注意用不同的css屬性。
核心代碼的改動就下面兩段,一個是增加了透明度漸變函數(shù)fade(),另一個是在pos()里面事先要先把圖片透明-->然后開始執(zhí)行fade()
pos()里增加一個代碼段:
if(this.li[i].o>=100){ //在圖片淡入之前先把圖片透明度置為透明
this.li[i].o = 0;
this.li[i].style.opacity = 0;
this.li[i].style.filter = 'alpha(opacity=0)';
}
this.li[i].f = setInterval(new Function(this.anthor+'.fade('+i+')'),20);
然后加一個功能函數(shù)fade()
fade:function(i){
if(this.li[i].o>=100){
clearInterval(this.li[i].f); //如果透明度變化完畢,清除計時器
if(!this.li.a){ //確保所有計時器都清除掉之后再開始自動運行。要不然會導(dǎo)致有控制器時點擊過快的話,計時器沒來得及清除就開始下一次變化,功能就亂了
this.auto();
}
}
else{ //透明度變化
this.li[i].o+=5;
this.li[i].style.opacity = this.li[i].o/100;
this.li[i].style.filter = 'alpha(opacity='+this.li[i].o+')';
}
}
好了,就這么簡單。不過還有一點要記住就是在pos()調(diào)用的最初一定要記得清除上次的計時器?。?
下面再把整個的源碼都貼一遍吧:
var Hongru={};
function H$(id){return document.getElementById(id)}
function H$$(c,p){return p.getElementsByTagName(c)}
Hongru.fader = function(){
function init(anthor,options){this.anthor=anthor; this.init(options);}
init.prototype = {
init:function(options){ //options參數(shù):id(必選):圖片列表父標(biāo)簽id;auto(可選):自動運行時間;index(可選):開始的運行的圖片序號
var wp = H$(options.id), // 獲取圖片列表父元素
ul = H$$('ul',wp)[0], // 獲取
li = this.li = H$$('li',ul);
this.a = options.auto?options.auto:2; //自動運行間隔
this.index = options.position?options.position:0; //開始運行的圖片序號(從0開始)
this.l = li.length;
this.cur = this.z = 0; //當(dāng)前顯示的圖片序號&&z-index變量
/* ==加入淡入淡出功能 ==*/
for(var i=0;i<this.l;i++){
this.li[i].o = 100; //為每一個圖片都設(shè)置一個透明度變化量
this.li[i].style.opacity = this.li[i].o/100; //非IE用opacity即可
this.li[i].style.filter = 'alpha(opacity='+this.li[i].o+')'; //IE用濾鏡
}
this.pos(this.index); //變換函數(shù)
},
auto:function(){
this.li.a = setInterval(new Function(this.anthor+'.move(1)'),this.a*1000);
},
move:function(i){//參數(shù)i有兩種選擇,1和-1,1代表運行到下一張,-1代表運行到上一張
var n = this.cur+i;
var m = i==1?n==this.l?0:n:n<0?this.l-1:n; //下一張或上一張的序號(注意三元選擇符的運用)
this.pos(m); //變換到上一張或下一張
},
pos:function(i){
clearInterval(this.li.a); //清除自動變換計時器
clearInterval(this.li[i].f); //清除淡入淡出效果計時器
this.z++;
this.li[i].style.zIndex = this.z; //每次讓下一張圖片z-index加一
this.cur = i; //綁定當(dāng)前顯示圖片的正確序號
this.li.a = false; //做一個標(biāo)記,下面要用到,表示清除計時器已經(jīng)完成
//this.auto(); //自動運行
if(this.li[i].o>=100){ //在圖片淡入之前先把圖片透明度置為透明
this.li[i].o = 0;
this.li[i].style.opacity = 0;
this.li[i].style.filter = 'alpha(opacity=0)';
}
this.li[i].f = setInterval(new Function(this.anthor+'.fade('+i+')'),20);
},
fade:function(i){
if(this.li[i].o>=100){
clearInterval(this.li[i].f); //如果透明度變化完畢,清除計時器
if(!this.li.a){ //確保所有計時器都清除掉之后再開始自動運行。要不然會導(dǎo)致有控制器時點擊過快的話,計時器沒來得及清除就開始下一次變化,功能就亂了
this.auto();
}
}
else{
this.li[i].o+=5;
this.li[i].style.opacity = this.li[i].o/100;
this.li[i].style.filter = 'alpha(opacity='+this.li[i].o+')';
}
}
}
return {init:init}
}();
大家要注意我寫的注釋,有些地方是比較關(guān)鍵的。
再看看運行效果吧:
[Ctrl+A 全選 注:引入外部Js需再刷新一下頁面才能執(zhí)行]
可能有人注意到了,這里的淡入淡出只是個頭銜,其實只有淡入效果,不過不礙事,效果其實和有淡出基本一樣,而且就算要淡出功能也僅僅需要改兩句話。呵呵
這一部分到此結(jié)束,下一部分會加入控制器。
開始之前,還是說說前文提到的關(guān)于把所有函數(shù)都寫在一個閉包內(nèi)的優(yōu)化問題。前文也提到了,因為我們在初始化的時候要調(diào)用的只是init,所以可以只把init寫入閉包,其他功能函數(shù)作為init的原型繼承方法來調(diào)用。所以前文的代碼其實可以這樣改寫:
復(fù)制代碼 代碼如下:
var Hongru={};
function H$(id){return document.getElementById(id)}
function H$$(c,p){return p.getElementsByTagName(c)}
Hongru.fader = function(){
function init(options){ //options參數(shù):id(必選):圖片列表父標(biāo)簽id;auto(可選):自動運行時間;index(可選):開始的運行的圖片序號
var wp = H$(options.id), // 獲取圖片列表父元素
ul = H$$('ul',wp)[0], // 獲取
li = this.li = H$$('li',ul);
this.a = options.auto?options.auto:2; //自動運行間隔
this.index = options.position?options.position:0; //開始運行的圖片序號(從0開始)
this.l = li.length;
this.cur = this.z = 0; //當(dāng)前顯示的圖片序號&&z-index變量
this.pos(this.index); //變換函數(shù)
}
init.prototype = {
auto:function(){
this.li.a = setInterval(new Function('Hongru.fader.move(1)'),this.a*1000);
},
move:function(i){//參數(shù)i有兩種選擇,1和-1,1代表運行到下一張,-1代表運行到上一張
var n = this.cur+i;
var m = i==1?n==this.l?0:n:n<0?this.l-1:n; //下一張或上一張的序號(注意三元選擇符的運用)
this.pos(m); //變換到上一張或下一張
},
pos:function(i){
clearInterval(this.li.a);
this.z++;
this.li[i].style.zIndex = this.z; //每次讓下一張圖片z-index加一
this.cur = i; //綁定當(dāng)前顯示圖片的正確序號
this.auto(); //自動運行
}
}
return {init:init}
}();
但是這樣其實是有問題的,不知道大家發(fā)現(xiàn)沒有,如果這樣改寫的話,在auto函數(shù)里就不能再調(diào)用‘Hongru.fader.move()'了,這是沒定義的,那有人會說,既然是init的原型繼承,那就調(diào)用'Hongru.fader.init.move()'不就對了嗎?其實也不對,我在以前的文章中就討論過這個問題http://www.cnblogs.com/hongru/archive/2010/10/09/1846636.html;init在沒有實例化之前是訪問不到它的prototype的,所以我們在這樣做的時候要注意兩個問題,
一個是初始化的時候要用new關(guān)鍵字對init實例化。
另外一個是在代碼內(nèi)部調(diào)用它的原型方法時也要通過我們實例化后的對象來調(diào)用,舉個例子,比如我們對上面的代碼初始化的時候應(yīng)該是這樣的
復(fù)制代碼 代碼如下:
var newFader = new Hongru.fader.init({ //這個new很重要
id:'fader'
});
如果我們在代碼里要調(diào)用init的方法要通過我們新建的實例化對象newFader來調(diào)用,比如在上面的auto函數(shù)里要調(diào)用init的move方法的話,就直接調(diào)用'newFader.move()',這樣才行。
可是這樣還有個小問題,就是必須要保證實例化的變量名和代碼中調(diào)用的一致,那么如果我改了我的初始化對象的名字,比如用newFader1,那么我還得去改源碼,這樣肯定是不行的,所以有個小技巧,就是在init里面多傳一個參數(shù),自己在做初始化的時候讓變量名和參數(shù)一致,然后在源碼里我們通過參數(shù)來調(diào)用。這樣問題就圓滿的解決了。
(ps:代碼里之所以使用new Function的原因也是因為這樣能沖破作用域鏈,這也是保證我們能這樣架構(gòu)我們代碼的條件之一。)
綜上:之前的代碼應(yīng)該這樣優(yōu)化:
復(fù)制代碼 代碼如下:
var Hongru={};
function H$(id){return document.getElementById(id)}
function H$$(c,p){return p.getElementsByTagName(c)}
Hongru.fader = function(){
function init(anthor,options){this.anthor=anthor; this.init(options);}
init.prototype = {
init:function(options){ //options參數(shù):id(必選):圖片列表父標(biāo)簽id;auto(可選):自動運行時間;index(可選):開始的運行的圖片序號
var wp = H$(options.id), // 獲取圖片列表父元素
ul = H$$('ul',wp)[0], // 獲取
li = this.li = H$$('li',ul);
this.a = options.auto?options.auto:2; //自動運行間隔
this.index = options.position?options.position:0; //開始運行的圖片序號(從0開始)
this.l = li.length;
this.cur = this.z = 0; //當(dāng)前顯示的圖片序號&&z-index變量
this.pos(this.index); //變換函數(shù)
},
auto:function(){
this.li.a = setInterval(new Function(this.anthor+'.move(1)'),this.a*1000);
},
move:function(i){//參數(shù)i有兩種選擇,1和-1,1代表運行到下一張,-1代表運行到上一張
var n = this.cur+i;
var m = i==1?n==this.l?0:n:n<0?this.l-1:n; //下一張或上一張的序號(注意三元選擇符的運用)
this.pos(m); //變換到上一張或下一張
},
pos:function(i){
clearInterval(this.li.a);
this.z++;
this.li[i].style.zIndex = this.z; //每次讓下一張圖片z-index加一
this.cur = i; //綁定當(dāng)前顯示圖片的正確序號
this.auto(); //自動運行
}
}
return {init:init}
}();
初始化時應(yīng)該這樣:
復(fù)制代碼 代碼如下:
var fader = new Hongru.fader.init('fader',{ //保證第一個參數(shù)和變量名一致
id:'fader'
});
好了,代碼的優(yōu)化方案到此結(jié)束。下面是第二部分效果的實現(xiàn):淡入淡出的效果
其實有了上面良好的代碼結(jié)構(gòu)和邏輯的話,加入淡入淡出效果是比較容易的,思路很簡單,在變化之前讓圖片透明,然后通過計時器讓透明度漸漸增加。只不過這里面有幾個邊界的判斷是比較重要的。同時透明度改變在ie和非ie下要注意用不同的css屬性。
核心代碼的改動就下面兩段,一個是增加了透明度漸變函數(shù)fade(),另一個是在pos()里面事先要先把圖片透明-->然后開始執(zhí)行fade()
pos()里增加一個代碼段:
復(fù)制代碼 代碼如下:
if(this.li[i].o>=100){ //在圖片淡入之前先把圖片透明度置為透明
this.li[i].o = 0;
this.li[i].style.opacity = 0;
this.li[i].style.filter = 'alpha(opacity=0)';
}
this.li[i].f = setInterval(new Function(this.anthor+'.fade('+i+')'),20);
然后加一個功能函數(shù)fade()
復(fù)制代碼 代碼如下:
fade:function(i){
if(this.li[i].o>=100){
clearInterval(this.li[i].f); //如果透明度變化完畢,清除計時器
if(!this.li.a){ //確保所有計時器都清除掉之后再開始自動運行。要不然會導(dǎo)致有控制器時點擊過快的話,計時器沒來得及清除就開始下一次變化,功能就亂了
this.auto();
}
}
else{ //透明度變化
this.li[i].o+=5;
this.li[i].style.opacity = this.li[i].o/100;
this.li[i].style.filter = 'alpha(opacity='+this.li[i].o+')';
}
}
好了,就這么簡單。不過還有一點要記住就是在pos()調(diào)用的最初一定要記得清除上次的計時器?。?
下面再把整個的源碼都貼一遍吧:
復(fù)制代碼 代碼如下:
var Hongru={};
function H$(id){return document.getElementById(id)}
function H$$(c,p){return p.getElementsByTagName(c)}
Hongru.fader = function(){
function init(anthor,options){this.anthor=anthor; this.init(options);}
init.prototype = {
init:function(options){ //options參數(shù):id(必選):圖片列表父標(biāo)簽id;auto(可選):自動運行時間;index(可選):開始的運行的圖片序號
var wp = H$(options.id), // 獲取圖片列表父元素
ul = H$$('ul',wp)[0], // 獲取
li = this.li = H$$('li',ul);
this.a = options.auto?options.auto:2; //自動運行間隔
this.index = options.position?options.position:0; //開始運行的圖片序號(從0開始)
this.l = li.length;
this.cur = this.z = 0; //當(dāng)前顯示的圖片序號&&z-index變量
/* ==加入淡入淡出功能 ==*/
for(var i=0;i<this.l;i++){
this.li[i].o = 100; //為每一個圖片都設(shè)置一個透明度變化量
this.li[i].style.opacity = this.li[i].o/100; //非IE用opacity即可
this.li[i].style.filter = 'alpha(opacity='+this.li[i].o+')'; //IE用濾鏡
}
this.pos(this.index); //變換函數(shù)
},
auto:function(){
this.li.a = setInterval(new Function(this.anthor+'.move(1)'),this.a*1000);
},
move:function(i){//參數(shù)i有兩種選擇,1和-1,1代表運行到下一張,-1代表運行到上一張
var n = this.cur+i;
var m = i==1?n==this.l?0:n:n<0?this.l-1:n; //下一張或上一張的序號(注意三元選擇符的運用)
this.pos(m); //變換到上一張或下一張
},
pos:function(i){
clearInterval(this.li.a); //清除自動變換計時器
clearInterval(this.li[i].f); //清除淡入淡出效果計時器
this.z++;
this.li[i].style.zIndex = this.z; //每次讓下一張圖片z-index加一
this.cur = i; //綁定當(dāng)前顯示圖片的正確序號
this.li.a = false; //做一個標(biāo)記,下面要用到,表示清除計時器已經(jīng)完成
//this.auto(); //自動運行
if(this.li[i].o>=100){ //在圖片淡入之前先把圖片透明度置為透明
this.li[i].o = 0;
this.li[i].style.opacity = 0;
this.li[i].style.filter = 'alpha(opacity=0)';
}
this.li[i].f = setInterval(new Function(this.anthor+'.fade('+i+')'),20);
},
fade:function(i){
if(this.li[i].o>=100){
clearInterval(this.li[i].f); //如果透明度變化完畢,清除計時器
if(!this.li.a){ //確保所有計時器都清除掉之后再開始自動運行。要不然會導(dǎo)致有控制器時點擊過快的話,計時器沒來得及清除就開始下一次變化,功能就亂了
this.auto();
}
}
else{
this.li[i].o+=5;
this.li[i].style.opacity = this.li[i].o/100;
this.li[i].style.filter = 'alpha(opacity='+this.li[i].o+')';
}
}
}
return {init:init}
}();
大家要注意我寫的注釋,有些地方是比較關(guān)鍵的。
再看看運行效果吧:
[Ctrl+A 全選 注:引入外部Js需再刷新一下頁面才能執(zhí)行]
可能有人注意到了,這里的淡入淡出只是個頭銜,其實只有淡入效果,不過不礙事,效果其實和有淡出基本一樣,而且就算要淡出功能也僅僅需要改兩句話。呵呵
這一部分到此結(jié)束,下一部分會加入控制器。
相關(guān)文章
javascript設(shè)計模式 – 迭代器模式原理與用法實例分析
這篇文章主要介紹了javascript設(shè)計模式 – 迭代器模式原理與用法,結(jié)合實例形式分析了javascript迭代器模式相關(guān)概念、原理、用法及操作注意事項,需要的朋友可以參考下2020-04-04bootstrap datetimepicker日期插件使用方法
這篇文章主要為大家詳細介紹了bootstrap datetimepicker的使用方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-01-01Echarts基本用法_動力節(jié)點Java學(xué)院整理
這篇文章主要介紹了Echarts基本用法,詳解的介紹了Echarts的基本用法和實例,有興趣的可以了解一下2017-08-08JavaScript實現(xiàn)QQ列表展開收縮擴展功能
這篇文章主要為大家詳細介紹了JavaScript實現(xiàn)QQ列表展開收縮擴展功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-10-10uniapp開發(fā)小程序?qū)崿F(xiàn)全局懸浮按鈕的代碼
這篇文章主要介紹了uniapp開發(fā)小程序如何實現(xiàn)全局懸浮按鈕,但是在uniapp中式?jīng)]有window對象,和dom元素的,需要獲取頁面上節(jié)點的幾何信息,具體實例代碼詳細跟隨小編一起看看吧2022-03-03配置Grunt的Task時通配符支持和動態(tài)生成文件名問題
這篇文章主要介紹了配置Grunt的Task時通配符支持和動態(tài)生成文件名問題,需要的朋友可以參考下2015-09-09