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