預載入和JavaScript Image()對象
很多high-res映像真的可以使 Web 網站更加整潔。但是它們也會使網站的訪問速度變慢——映像是檔案,檔案使用頻寬,頻寬直接與等待時間相關。是該瞭解如何通過一個叫做映像預載入(preloading)的技巧來提高 Web 網站的訪問速度的時候了。
映像預載入
對於瀏覽器載入映像來說,只有在對映像發送一個 HTTP請求之後,它們才會被瀏覽器載入,對映像的 HTTP 要求要麼使用 <img> 標記,要麼通過方法調用實現。如果使用 JavaScript 指令碼來處理在 mouseover 事件時交換映像,或者在一段時間之後自動更改映像,那麼在從伺服器擷取映像時可能要等上幾秒鐘到幾分鐘的時間。如果使用一個慢速的 網際網路連線,或者要擷取的映像非常大,或者其它一些情況,這種現象就特別明顯;這樣,延遲就造成你不能達到自己期望的效果。
一些瀏覽器採用一些措施來緩解這一問題,比如試圖通過在本機快取中儲存映像,從而使隨後對映像的調用能夠立即被滿足;但是在映像第一次被調用時依然會存在一些延遲。預載入是在需要映像之前將其下載到緩衝的一種方法。通過這一措施,當真正需要映像時,它就可以被立即從緩衝中取出,從而能夠立即顯示。
Image() 對象
預載入映像最簡單的方法是在 JavaScript 中執行個體化一個新 Image() 對象,然後將需要載入的映像的 URL 作為參數傳入。假設我們有一個映像叫做heavyimagefile.jpg,在使用者的滑鼠放到一個已經顯示的映像之上時,我們希望顯示這個映像。為了預載入這一映像從而得到較快的回應時間,我們簡單地建立一個 Image() 對象 heavyImage,然後在 onLoad() 事件處理器中將其同時載入。 複製代碼 代碼如下:<html>
<head>
<script language = "JavaScript">
function preloader()
{
heavyImage = new Image();
heavyImage.src = "heavyimagefile.jpg";
}
</script>
</head>
<body onLoad="javascript:preloader()">
<a href="#" onMouseOver="javascript:document.img01.src='heavyimagefile.jpg'">
<img name="img01" src="justanotherfile.jpg"></a>
</body>
</html>
請注意,映像標記本身不能處理 onMouseOver() 和 onMouseOut() 事件,這就是上例中<img> 標記被包含在一個<a> 標記之中的原因,<a> 標記支援這兩個事件類型。
使用數組載入多個映像
在實際應用中,我們可能需要預載入多個映像,而不止一個;例如,在一個包含多個映像翻卷的功能表列中,或者在我們試圖建立凹凸貼圖時,都需要預載入多個映像。其實這並不困難,只要使用 JavaScript 的數組即可實現,如下例所示: 複製代碼 代碼如下:<script language="JavaScript">
function preloader()
{
// counter
var i = 0;
// create object
imageObj = new Image();
// set image list
images = new Array();
images[0]="image1.jpg"
images[1]="image2.jpg"
images[2]="image3.jpg"
images[3]="image4.jpg"
// start preloading
for(i=0; i<=3; i )
{
imageObj.src=images[i];
}
}
</script>
在上面的例子中,我們定義一個變數 i和一個 Image() 對象 imageObj。然後定義了一個新數組 images[],每個數組元素儲存要被預載入的映像。最後,建立一個 for() 迴圈來處理整個數組,並將每個元素賦給 Image() 對象,這樣將其載入到緩衝中。
onLoad() 事件處理器
像很多 JavaScript 的其它對象一樣,Image() 對象也有一些事件處理器。其中最有用的一個肯定是 onLoad() 處理器,它在映像完全載入之後調用。這個事件處理器可以與一個自訂函數聯絡起來,以在映像完全載入之後執行一些特定的任務。下面的例子說明了這一點,在這個例子中,首先在映像載入時顯示一個“please wait”螢幕,然後在載入完成時將瀏覽器轉到一個新的 URL。 複製代碼 代碼如下:<html>
<head>
<script language="JavaScript">
// create an image object
objImage = new Image();
// set what happens once the image has loaded objImage.onLoad=imagesLoaded();
// preload the image file
objImage.src='images/image1n.gif';
// function invoked on image load
function imagesLoaded()
{
document.location.href='index2.html';
}
</script>
</head>
<body>
Please wait, loading images...
</body>
</html>
當然,你還可以建立一個映像數組然後在其上進行迴圈操作,預載入每個映像,然後在每一階段跟蹤被載入映像的數目。一旦所有映像載入完畢,根據事件處理器的程式邏輯,它就可以將瀏覽器帶入下一個頁面(或者執行其它任務)。
預載入和多狀態菜單
現在,如何在實際應用程式中使用所有你學到的理論?下面的這段代碼是我最近偶爾編寫的一個功能表列,這個功能表列由一些按鈕(映像連結)組成,每個按鈕具有三種狀態:正常、懸停和點擊。因為按鈕具有多種狀態,所以很有必要使用映像預載入,以保證菜單的狀態能夠快速地反應。清單A中的代碼說明了實現方法。
清單A 中的HTML 程式碼設定了一個由四個按鈕組成的菜單,每個按鈕具有三種狀態:正常、懸停和點擊。需求如下:
# 當滑鼠移動到一個正常狀態下的按鈕之上時,它變為懸停狀態。在滑鼠離開之後,按鈕恢複為正常狀態。
# 在滑鼠點擊一個按鈕時,按鈕變為點擊狀態。在其它按鈕被點擊之前,它將保留這一狀態。
# 如果一個按鈕被點擊,其它按鈕的狀態都不能為點擊狀態。其它按鈕只能為懸停狀態或正常狀態。
# 在同一時間只能有一個按鈕被點擊。
# 在同一時間只能有一個按鈕處於懸停狀態。
第一個任務是設定數組,用於儲存菜單每個狀態的映像。與這些數組元素對應的 <img> 也在 HTML 文檔本文(body)中建立,並順序地命名。請注意,數組值的索引是從0開始的,雖然對應的 <img> 元素的命名是從1開始的——這樣就需要在指令碼後面的部分進行計算調整。
函數 preloadImage() 負責將所有的映像儲存到緩衝中,以使滑鼠運動的回應時間最小。for() 迴圈用於迭代第一步建立的映像,並在每次迭代中預載入一個映像。