paulwong

          My Links

          Blog Stats

          常用鏈接

          留言簿(67)

          隨筆分類(1391)

          隨筆檔案(1149)

          文章分類(7)

          文章檔案(10)

          相冊(cè)

          收藏夾(2)

          AI

          Develop

          E-BOOK

          Other

          養(yǎng)生

          微服務(wù)

          搜索

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          60天內(nèi)閱讀排行

          javascript圖片瀏覽器的核心——圖片預(yù)加載

          網(wǎng)站開發(fā)時(shí)經(jīng)常需要在某個(gè)頁(yè)面需要實(shí)現(xiàn)對(duì)大量圖片的瀏覽,如果考慮流量的話,大可以像pconline一樣每個(gè)頁(yè)面只顯示一張圖片,讓用戶每看一張圖片就需要重新下載一下整個(gè)頁(yè)面。不過(guò),在web2.0時(shí)代,更多人愿意用javascript來(lái)實(shí)現(xiàn)一個(gè)圖片瀏覽器,讓用戶無(wú)需等待過(guò)長(zhǎng)的時(shí)間就能看到其他圖片。

          知道了一張圖片的地址,需要把它在一個(gè)固定大小的html容器(可以是div等)里邊顯示出來(lái),最重要的當(dāng)然是需要知道這張即將顯示的圖片的寬和高,然后再結(jié)合容器的寬和高,按照一定的縮放比例使圖片顯示出來(lái)。因此,實(shí)現(xiàn)圖片預(yù)加載就成為圖片瀏覽器的核心功能了。

          做過(guò)圖片翻轉(zhuǎn)效果的朋友其實(shí)都知道,要讓圖片輪換的時(shí)候不出現(xiàn)等待,最好是先讓圖片下載到本地,讓瀏覽器緩存起來(lái)。這時(shí),一般都會(huì)用到j(luò)s里邊的Image對(duì)象。一般的手段無(wú)非這樣:

          function preLoadImg(url) {
          var img = new Image();
          img.src 
          = url;
          }


          通過(guò)調(diào)用preLoadImg函數(shù),傳入圖片的url,就能使圖片預(yù)先下載下來(lái)了。實(shí)際上,這里用到的預(yù)下載功能也和這基本一致。圖片預(yù)下載下來(lái)后,通過(guò) img的width和height屬性,就能知道圖片的寬和高了。但是需要考慮到,在做圖片瀏覽器功能時(shí),圖片都是實(shí)時(shí)顯示的。比如你點(diǎn)了顯示的按鈕,這個(gè)時(shí)候才會(huì)調(diào)用上邊類似的代碼來(lái)加載圖片。因此,如果你直接用img.width的時(shí)候,圖片還沒有完全下載下來(lái)。因此,需要用一些異步的方法,等到圖片下載完畢的時(shí)候才會(huì)再對(duì)img的width和height進(jìn)行調(diào)用。 實(shí)現(xiàn)這樣的異步方法實(shí)際上不難,圖片的下載完畢事件也很簡(jiǎn)單,就是簡(jiǎn)單的onload事件。因此,我們可以寫出下面的代碼:


          function loadImage(url, callback) {
          var img = new Image();
          img.src 
          = url;

          img.onload 
          = function()//圖片下載完畢時(shí)異步調(diào)用callback函數(shù)。
          callback.call(img); // 將callback函數(shù)this指針切換為img。
          }
          ;
          }


          好了,再來(lái)寫一個(gè)測(cè)試用例。


          function imgLoaded(){
          alert(
          this.width);
          }


          <input type="button" value="loadImage" onclick="loadImage('aaa.jpg',imgLoaded)"/>

          在firefox中測(cè)試一下,發(fā)現(xiàn)不錯(cuò),果然和預(yù)想的效果一樣,在圖片下載后,就會(huì)彈出圖片的寬度來(lái)。無(wú)論點(diǎn)擊多少次或者刷新結(jié)果都一樣。

          不過(guò),做到這一步,先別高興太早——還需要考慮一下瀏覽器的兼容性,于是,趕緊到ie里邊測(cè)試一下。沒錯(cuò),同樣彈出了圖片的寬度。但是,再點(diǎn)擊load的時(shí)候,情況就不一樣了,什么反應(yīng)都沒有了。刷新一下,也同樣如此。

          經(jīng)過(guò)對(duì)多個(gè)瀏覽器版本的測(cè)試,發(fā)現(xiàn)ie6、opera都會(huì)這樣,而firefox和safari則表現(xiàn)正常。其實(shí),原因也挺簡(jiǎn)單的,就是因?yàn)闉g覽器的緩存了。當(dāng)圖片加載過(guò)一次以后,如果再有對(duì)該圖片的請(qǐng)求時(shí),由于瀏覽器已經(jīng)緩存住這張圖片了,不會(huì)再發(fā)起一次新的請(qǐng)求,而是直接從緩存中加載過(guò)來(lái)。對(duì)于 firefox和safari,它們視圖使這兩種加載方式對(duì)用戶透明,同樣會(huì)引起圖片的onload事件,而ie和opera則忽略了這種同一性,不會(huì)引起圖片的onload事件,因此上邊的代碼在它們里邊不能得以實(shí)現(xiàn)效果。

          怎么辦呢?最好的情況是Image可以有一個(gè)狀態(tài)值表明它是否已經(jīng)載入成功了。從緩存加載的時(shí)候,因?yàn)椴恍枰却@個(gè)狀態(tài)值就直接是表明已經(jīng)下載了,而從http請(qǐng)求加載時(shí),因?yàn)樾枰却螺d,這個(gè)值顯示為未完成。這樣的話,就可以搞定了。

          經(jīng)過(guò)一些分析,終于發(fā)現(xiàn)一個(gè)為各個(gè)瀏覽器所兼容的Image的屬性——complete。所以,在圖片onload事件之前先對(duì)這個(gè)值做一下判斷即可。最后,代碼變成如下的樣子:


          function loadImage(url, callback) {
          var img = new Image(); //創(chuàng)建一個(gè)Image對(duì)象,實(shí)現(xiàn)圖片的預(yù)下載
          img.src = url;

          if (img.complete) // 如果圖片已經(jīng)存在于瀏覽器緩存,直接調(diào)用回調(diào)函數(shù)
          callback.call(img);
          return// 直接返回,不用再處理onload事件
          }


          img.onload 
          = function () //圖片下載完畢時(shí)異步調(diào)用callback函數(shù)。
          callback.call(img);//將回調(diào)函數(shù)的this替換為Image對(duì)象
          }
          ;
          }
          ;

          經(jīng)過(guò)這么一番折騰,總算是讓各個(gè)瀏覽器都能滿足我們的目標(biāo)了。雖然代碼很簡(jiǎn)單,但是卻把圖片瀏覽器中最核心的問題解決掉了,接下來(lái)你所要做的,僅僅是圖片如何呈現(xiàn)的問題了。

          posted on 2010-11-13 17:24 paulwong 閱讀(491) 評(píng)論(0)  編輯  收藏 所屬分類: DHTML

          主站蜘蛛池模板: 莱芜市| 华阴市| 兴隆县| 瑞金市| 郓城县| 绥芬河市| 达尔| 合川市| 张家口市| 长顺县| 晋城| 洪洞县| 莱阳市| 濮阳市| 全南县| 闽清县| 化州市| 京山县| 清徐县| 蕉岭县| 卓尼县| 张家川| 西吉县| 乐至县| 禹城市| 东丰县| 库伦旗| 银川市| 方城县| 彭泽县| 兰坪| 鄄城县| 德昌县| 伊金霍洛旗| 江口县| 玉山县| 沐川县| 宜君县| 皮山县| 左云县| 肇源县|