日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
看HTML5如何創(chuàng)建一個圖片瀏覽器

HTML Canvas 介紹

創(chuàng)新互聯(lián)專業(yè)為企業(yè)提供云夢網(wǎng)站建設(shè)、云夢做網(wǎng)站、云夢網(wǎng)站設(shè)計、云夢網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計與制作、云夢企業(yè)網(wǎng)站模板建站服務(wù),十年云夢做網(wǎng)站經(jīng)驗,不只是建網(wǎng)站,更提供有價值的思路和整體網(wǎng)絡(luò)服務(wù)。

HTML5 是目前正在討論的新一代 HTML 標準,它代表了現(xiàn)在 Web 領(lǐng)域的最新的發(fā)展方向。在 HTML5 標準中,加入了新的多樣的內(nèi)容描述標簽,直接支持表單驗證,視頻和音頻標簽,網(wǎng)頁元素的拖拽,離線存儲,工作線程等等。當然,其中一個最令人激動的新特性就是新的標簽類型 Canvas,開發(fā)人員可以通過該標簽,在網(wǎng)頁上直接用腳本進行繪圖,產(chǎn)生各種 2D 渲染的效果。所以有人預(yù)言,HTML5 將是 Flash 和 Silverlight 的“殺手”。從 Firefox 1.5 開始就已經(jīng)支持 Canvas,Safari 也是很早就開始支持 Canvas。新的瀏覽器比如 Chrome 也是從一開始就支持。但遺憾的是,到目前為止,IE 一直不支持該標準。

下面內(nèi)容將通過如何用 Canvas 來制作一個圖片瀏覽器的具體實例,來說明 Canvas 的各種 API,如何使用這些 API 以及如何應(yīng)用到工程中去。本文將首先介紹如何創(chuàng)建圖片瀏覽器的網(wǎng)頁和 JavaScript 類,介紹整體界面的設(shè)計,然后介紹如何用 Canvas 的 API 來繪制 2D 圖形,然后介紹如何在 Canvas 上加載和繪制圖像,接下來本例會在圖片瀏覽器中加入其他基于 Canvas 的效果,最后是總結(jié)和展望。

創(chuàng)建圖片瀏覽器框架

創(chuàng)建文件

首先我們創(chuàng)建一個新的 html 文件 thumbnail.html,加入如清單 1 所示的內(nèi)容:

清單 1.thumbnail.html

  
 
 
 
  1.  
  2.   
  3.   
  4.   Canvas Based Thumbnail 
  5.    
  6.     body { 
  7.     background: black; 
  8.     color: white; 
  9.    font: 24pt Baskerville, Times, Times New Roman, serif; 
  10.     padding: 0; 
  11.     margin: 0; 
  12.     overflow: hidden; 
  13.     } 
  14.    
  15.    
  16.   
  17.   
  18.    
  19.   
  20.   

這里我們可以看到,canvas 是 html 的一個新的標簽,其用法和其他標簽一樣,只不過它的高和寬有獨立的屬性而不是在 css 定義的。如果我們要設(shè)置一個 Canvas 區(qū)域的寬高,必須定義為 而不能是 。在上面的 html 文件中我們沒有直接定義 Canvas 區(qū)域的大小,而是在 JavaScript 中動態(tài)定義,下面將要詳細說明。

現(xiàn)在我們創(chuàng)建一個新的 JavaScript 文件 thumbnail.js 來在 Canvas 中繪制圖像,我們設(shè)計一個 thumbnail 類,該類可以處理用戶事件,繪制圖形,顯示圖像。然后在 window.onload 事件中加載該類,代碼如清單 2 所示:

清單 2 .thumbnail.js

  
 
 
 
  1. function thumbnail() { 
  2.     this.load = function() 
  3.     } 
  4.  } 
  5.  window.onload = function() { 
  6.     thumb = new thumbnail(); 
  7.     thumb.load(); 
  8.  } 

代碼定義了一個初始化函數(shù) load,并且聲明了 thumbnail 類,這樣我們就可以在 thumbnail 類中添加代碼,在 Canvas 上繪制各種圖形以及圖像了。

設(shè)計界面

我們?yōu)檫@個圖片瀏覽頁面設(shè)計這樣一種界面,圖片通過縮放占滿全部網(wǎng)頁空間,在中間下方,繪制一個導(dǎo)航欄,顯示縮略圖,當點擊縮略圖時,該圖片顯示到網(wǎng)頁中。同時,如果鼠標懸停在某個縮放圖上,則顯示一個大一點的預(yù)覽圖用來供用戶預(yù)覽。在導(dǎo)航欄的左右兩邊,添加 2 個按鈕,用于翻頁顯示上一頁和下一頁的縮略圖。對導(dǎo)航欄上所有控件的尺寸大小和位置如圖所示的方案。這樣,我們就可以按照該方案在 Canvas 上繪制這些控件了。

界面設(shè)計

用 Canvas 繪制圖形

繪制導(dǎo)航框

首先我們繪制如圖所示的一個導(dǎo)航欄。在左右兩邊各有一個按鈕,按鈕上顯示一個三角形的指示圖形。當鼠標放到一個按鈕上時,按鈕的背景色能變成高亮的顏色,顯示當前選中的按鈕。

導(dǎo)航框

清單 3 顯示了繪制圖 2 所示的導(dǎo)航欄的代碼片段。

清單 3 . 繪制導(dǎo)航框代碼

  
 
 
 
  1.             
  2. function thumbnail() { 
  3.    const NAVPANEL_COLOR = 'rgba(100, 100, 100, 0.2)';    // 導(dǎo)航欄背景色
  4.    const NAVBUTTON_BACKGROUND = 'rgb(40, 40, 40)';  // 導(dǎo)航欄中 button 的背景色
  5.    const NAVBUTTON_COLOR = 'rgb(255, 255, 255)';   //button 的前景色
  6.    const NAVBUTTON_HL_COLOR = 'rgb(100, 100, 100)';   //button 高亮?xí)r的前景色
  7.    var canvas = document.getElementById('canvas');   // 獲得 canvas 對象
  8.    var context = canvas.getContext('2d');    // 獲得上下文對象
  9.    // 繪制左邊 button 
  10.    function paintLeftButton(navRect, color) { 
  11.        //left button 
  12.        lButtonRect = { 
  13.            x: navRect.x + NAVBUTTON_XOFFSET, 
  14.            y: navRect.y + NAVBUTTON_YOFFSET, 
  15.            width: NAVBUTTON_WIDTH, 
  16.            height: navRect.height - NAVBUTTON_YOFFSET * 2 
  17.        } 
  18.        context.save(); 
  19.        context.fillStyle = color; 
  20.        context.fillRect(lButtonRect.x, lButtonRect.y, 
  21. lButtonRect.width, lButtonRect.height); 
  22.        //left arrow 
  23.        context.save(); 
  24.        context.fillStyle = NAVBUTTON_COLOR; 
  25.        context.beginPath(); 
  26.        context.moveTo(lButtonRect.x + NAVBUTTON_ARROW_XOFFSET, 
  27. lButtonRect.y + lButtonRect.height/2); 
  28.        context.lineTo(lButtonRect.x + lButtonRect.width - NAVBUTTON_ARROW_XOFFSET, 
  29. lButtonRect.y + NAVBUTTON_ARROW_YOFFSET); 
  30.        context.lineTo(lButtonRect.x + lButtonRect.width - NAVBUTTON_ARROW_XOFFSET, 
  31. lButtonRect.y + lButtonRect.height - NAVBUTTON_ARROW_YOFFSET); 
  32.        context.lineTo(lButtonRect.x + NAVBUTTON_ARROW_XOFFSET, 
  33. lButtonRect.y + lButtonRect.height/2); 
  34.        context.closePath(); 
  35.        context.fill(); 
  36.        context.restore(); 
  37.        context.restore(); 
  38.    } 

如上所述,在頁面 html 中我們聲明了 元素。當需要在 區(qū)域繪制圖形時,我們需要獲得繪制圖形的上下文對象,在一個上下文對象中,保存了當前的初始坐標位置,顏色,風(fēng)格等等信息。這里我們通過如清單 4 的語句獲取 Canvas 的 2 維繪圖的上下文對象。

清單 4. 獲得繪圖上下文

  
 
 
 
  1. var canvas = document.getElementById('canvas'); 
  2. var context = canvas.getContext('2d'); 

獲得上下文對象之后,我們就可以通過 Canvas 提供的 API 來進行繪畫了。在清單 5 中,我們使用了矩形的繪制函數(shù)來繪制整個導(dǎo)航欄背景和左右兩個按鈕。所下所示:

清單 5. 矩形繪制函數(shù)

  
 
 
 
  1. fillRect(x,y,width,height): 繪制一個填充的矩形
  2. strokeRect(x,y,width,height): 給一個矩形描邊
  3. clearRect(x,y,width,height): 清除該矩形內(nèi)所有內(nèi)容使之透明

例如,我們要繪制一個簡單的矩形可以用如清單 6 所示代碼:

清單 6. 繪制簡單矩形

  
 
 
 
  1. var canvas = document.getElementById('canvas'); 
  2. var context = canvas.getContext('2d'); 
  3. context.fillStyle = 'black'; 
  4. context.fillRect(0, 0, 50, 50); 
  5. context.clearRect(0, 0, 20, 20); 
  6. context.strokeRect(0, 0, 20, 20); 

我們繪制該導(dǎo)航框時,需要在左右兩邊各繪制一個三角形,對于除了矩形以外的所有多邊形,必須得通過路徑來繪制,常用的路徑相關(guān)函數(shù)有 :

清單 7. 繪制路徑函數(shù)

  
 
 
 
  1. beginPath(): 開始一段路徑 
  2. closePath(): 結(jié)束一段路徑
  3. moveTo(x,y)  : 移動起始點到某點
  4. lineTo(x,y) : 繪制線段到目標點

這樣,我們在繪制三角形的時候,只需要確定三個頂點的坐標,就可以通過 lineTo 函數(shù)繪制三條線段,但是,我們還需要一個函數(shù)在該三角形區(qū)域內(nèi)填充顏色,這樣需要用到填充和描邊的函數(shù)和樣式:

清單 8. 填充和描邊樣式

  
 
 
 
  1. fillStyle = color : 設(shè)置填充顏色
  2. storkeStyle = color : 設(shè)置描變顏色

這里 color 值可以是標準的 CSS 顏色值,還可以通過 rgba 函數(shù)設(shè)置透明度。我們可以如下設(shè)置:

清單 9. 填充樣式舉例

  
 
 
 
  1. context.fillStyle = "white"; 
  2. context.strokeStyle = "#FFA500"; 
  3. context.fillStyle = "rgb(255,165,0)"; 
  4. context.fillStyle = "rgba(255,165,0,1)"; 

同樣,當需要填充顏色樣式或者描邊時,有如下函數(shù):

清單 10. 填充和描邊函數(shù)

  
 
 
 
  1. stroke() : 按照當前描邊樣式描邊當前路徑
  2. fill() : 按照當前填充樣式填充路徑所描述的形狀

這樣,用上述幾個函數(shù),我們繪制一個三角形時,可以用如下語句:

清單 11. 繪制三角形代碼

  
 
 
 
  1. var canvas = document.getElementById('canvas'); 
  2. var context = canvas.getContext('2d'); 
  3. context.fillStyle = 'black'; 
  4. context.beginPath(); 
  5. context.moveTo(0,0); 
  6. context.lineTo(10,0); 
  7. context.lineTo(10,10); 
  8. context.lineTo(0,0); 
  9. context.closePath(); 
  10. context.fill(); 

在清單 3 中,我們還聲明了一些常量來定義導(dǎo)航欄的各種控件的大小,其中長度值都是以像素為單位的。這樣我們繪制了整個導(dǎo)航欄,但我們現(xiàn)在需要當鼠標放到按鈕上時,按鈕的前景色能夠高亮,顯示當前選中的按鈕。這就需要我們在代碼中響應(yīng)用戶事件,并進行不同類型的繪制。

響應(yīng)用戶事件

響應(yīng)用戶事件和普通的 DOM 編程類似,如清單 12 所示:

清單 12. 響應(yīng)鼠標移動時間

  
 
 
 
  1. var lastMousePos;    // 當前鼠標位置
  2. this.load = function() { 
  3.     //event binding 
  4.     canvas.onmousemove = onMouseMove; 
  5. function onMouseMove(event) { 
  6.     lastMousePos = {x:event.clientX, y:event.clientY}; 
  7.     paint(); 
  8. function pointIsInRect(point, rect) { 
  9.     return (rect.x < point.x && point.x < rect.x + rect.width && 
  10.             rect.y < point.y && point.y < rect.y + rect.height); 
  11. function paint() { 
  12.     context.clearRect(0, 0, canvas.width, canvas.height); 
  13.     var paintInfo = {inLeftBtn:false, inRightBtn:false} 
  14.     if (lastMousePos && navRect && lButtonRect && rButtonRect) { 
  15.         if (pointIsInRect(lastMousePos, navRect)) { 
  16.             paintInfo.inLeftBtn = pointIsInRect(lastMousePos, lButtonRect); 
  17.             paintInfo.inRightBtn = pointIsInRect(lastMousePos, rButtonRect); 
  18.         } 
  19.     } 
  20.     paintNavigator(paintInfo); 

這樣我們就繪制了一個完整的導(dǎo)航欄,它能夠響應(yīng)鼠標移動事件,并高亮當前選中的按鈕。下面我們需要加載和顯示圖片,這就需要用到 Canvas 的繪制圖像函數(shù)。


用 Canvas 繪制圖像

加載和顯示圖像

加載和顯示圖像的代碼片段如清單 13 所示:

清單 13. 加載和顯示圖像

  
 
 
 
  1.    const PAINT_INTERVAL = 20;  // 循環(huán)間隔
  2.    const PAINT_SLOW_INTERVAL = 20000;   
  3.    const IDLE_TIME_OUT = 3000;  // 空閑超時時間
  4.    // 定義全部圖片 URL 數(shù)組,在本例中,所有圖片保存在和網(wǎng)頁同目錄中
  5.    var imageLocations = [ 
  6.    '2006109173628.jpg', 
  7.    '2007310132939.jpg', 
  8.    '200733094828-1.jpg'
  9.    ]; 
  10.   // 加載圖片
  11.    function loadImages() { 
  12.        var total = imageLocations.length; 
  13.        var imageCounter = 0; 
  14.        var onLoad = function(err, msg) { 
  15.            if (err) { 
  16.                console.log(msg); 
  17.            } 
  18.            imageCounter++; 
  19.            if (imageCounter == total) { 
  20.                loadedImages = true; 
  21.            } 
  22.        } 
  23.        for (var i = 0; i < imageLocations.length; i++) { 
  24.            var img = new Image(); 
  25.            img.onload = function() { onLoad(false); }; 
  26.            img.onerror = function() { onLoad(true, e);}; 
  27.            img.src = imageLocations[i]; 
  28.            images[i] = img; 
  29.        } 
  30.    } 
  31.    // 繪制圖片
  32.    function paintImage(index) { 
  33.        if (!loadedImages) 
  34.            return; 
  35.        var image = images[index]; 
  36.        var screen_h = canvas.height; 
  37.        var screen_w = canvas.width; 
  38.        var ratio = getScaleRatio({width:image.width, height:image.height}, 
  39. {width:screen_w, height:screen_h}); 
  40.    var img_h = image.height * ratio; 
  41.    var img_w = image.width * ratio; 
  42.    context.drawImage(image, (screen_w - img_w)/2, (screen_h - img_h)/2, img_w, img_h); 
  43.    } 

在清單 13 的代碼中,我們更新了主繪制函數(shù) paint,加入了 paintImage 函數(shù),在 paintImage 函數(shù)中,利用 Canvas 的 drawImage 函數(shù),在整個 Canvas 區(qū)域,盡可能大地縮放圖片并顯示在 Canvas 中,其最佳縮放比例如所示 :

最佳縮放比例示例
 

這里縮放比例是通過本例所定義的函數(shù) getScaleRatio 來獲得的,其詳細代碼見附件。這樣我們可以在 Canvas 上繪制圖像,繪制圖像的函數(shù)定義如下 :

清單 14. 繪制圖像函數(shù)

  
 
 
 
  1. drawImage(image, x, y)   image 為一個圖像或者 Canvas 對象,x,y 為圖片所要放至位置的左上角坐標

但該函數(shù)還無法滿足我們的要求,我們需要縮放圖片到一個最佳大小,這就需要 Canvas 繪制圖片函數(shù)的另外一種形式:

清單 15. 繪制圖像函數(shù) 2

  
 
 
 
  1. drawImage(image, x, y, width, height)     width, height 為圖像在目標 Canvas 上的大小

該函數(shù)將圖片縮放到 width 和 height 所指定的大小并顯示出來。我們通過函數(shù) getScaleRatio 來計算最佳縮放大小,然后就可以通過如清單 15 所示來繪制最佳大小的圖片。

繪制圖片需要傳入一個 image 對象,它一般是一個圖片或者 Canvas 對象。也就是說你可以從一個 URL 中下載圖片顯示在 Canvas 中,也可以在一個 Canvas 中顯示另外一個 Canvas 中繪制的圖形。通過如清單 16 所示的代碼來加載圖片:

清單 16. 加載圖片代碼

  
 
 
 
  1. var onLoad = function(err, msg) { 
  2.     if (err)   console.log(msg); 
  3. var img = new Image(); 
  4. img.onload = function() { onLoad(false); }; 
  5. img.onerror = function() { onLoad(true, e);}; 
  6. img.src = ‘ myImage.png ’ ;  // 設(shè)置源路徑

在整個程序中,我們利用了 setInterval 函數(shù)加入了一個定時器來觸發(fā)主循環(huán),用于不斷循環(huán)等待全部圖片加載。當?shù)却龝r間超過一個閥值之后,主循環(huán)進入 idle 狀態(tài),該循環(huán)不僅能夠用于等待全部圖片加載,也可以用于繪制動畫效果,我們在后面將會講到如何利用該主循環(huán)來制作動態(tài)效果。

繪制縮略圖

下一步需要在導(dǎo)航欄中繪制每個圖片的縮略圖,該縮略圖必須按照最優(yōu)的大小和間隔排列在導(dǎo)航欄中,同時縮略圖必須經(jīng)過裁剪,獲得最優(yōu)的顯示區(qū)域。整體效果如圖所示:

縮略圖效果
 

實現(xiàn)代碼片段如清單 17 所示:

清單 17. 縮略圖代碼

  
 
 
 
  1.    const HL_OFFSET = 3;   
  2.    const THUMBNAIL_LENGTH = NAVPANEL_HEIGHT - NAVBUTTON_YOFFSET*2;   // 縮略圖顯示區(qū)域的高度
  3.    const MIN_THUMBNAIL_LENGTH = 10;  // 最小縮略圖間隔
  4.    var currentImage = 0;   // 當前圖片序號
  5.    var firstImageIndex = 0;  // 當前縮略圖中第一張圖片序號
  6.    var thumbNailCount = 0;  // 當前顯示的縮略圖數(shù)
  7.    var maxThumbNailCount = 0;  // 最大能夠顯示的縮略圖數(shù)
  8.    // 繪制縮略圖
  9.    function paintThumbNails(inThumbIndex) { 
  10.        if (!loadedImages) 
  11.            return; 
  12.        
  13.        if(inThumbIndex != null) { 
  14.            inThumbIndex -= firstImageIndex; 
  15.        } else { 
  16.            inThumbIndex = -1; 
  17.        } 
  18.        var thumbnail_length = rButtonRect.x - lButtonRect.x - lButtonRect.width; 
  19.        maxThumbNailCount = Math.ceil(thumbnail_length / THUMBNAIL_LENGTH); 
  20.        var offset = (thumbnail_length - THUMBNAIL_LENGTH * maxThumbNailCount) / 
  21. (maxThumbNailCount + 1); 
  22.        if (offset < MIN_THUMBNAIL_LENGTH) { 
  23.            maxThumbNailCount = Math.ceil(thumbnail_length/ (THUMBNAIL_LENGTH + 
  24. MIN_THUMBNAIL_LENGTH)); 
  25.            offset = (thumbnail_length - THUMBNAIL_LENGTH * maxThumbNailCount) / 
  26. (maxThumbNailCount + 1); 
  27.        } 
  28.        thumbNailCount = maxThumbNailCount > imageCount - firstImageIndex? 
  29. imageCount - firstImageIndex: maxThumbNailCount; 
  30.        imageRects = new Array(thumbNailCount); 
  31.        for (var i = 0; i < thumbNailCount; i++) { 
  32.            image = images[i+firstImageIndex]; 
  33.            context.save(); 
  34.            var x = lButtonRect.x + lButtonRect.width + (offset+THUMBNAIL_LENGTH)*i; 
  35.            srcRect = getSlicingSrcRect({width:image.width, height:image.height}, 
  36. {width:THUMBNAIL_LENGTH, height: THUMBNAIL_LENGTH}); 
  37.            imageRects[i] = { 
  38.                image:image, 
  39.                rect: { 
  40.                    x:x+offset, 
  41.                    y:inThumbIndex == i? navRect.y+NAVBUTTON_YOFFSET-HL_OFFSET: 
  42. navRect.y+NAVBUTTON_YOFFSET, 
  43.                    height: THUMBNAIL_LENGTH, 
  44.                    width: THUMBNAIL_LENGTH 
  45.                } 
  46.            } 
  47.            context.translate(x, navRect.y); 
  48.            context.drawImage(image, srcRect.x, srcRect.y, 
  49. srcRect.width, srcRect.height, 
  50. offset, imageRects[i].rect.y - navRect.y, 
  51. THUMBNAIL_LENGTH, THUMBNAIL_LENGTH); 
  52.            context.restore(); 
  53.        } 
  54.    } 

清單 17 的代碼使用了 Canvas 中坐標轉(zhuǎn)換的方法來繪制每張縮略圖。轉(zhuǎn)換坐標函數(shù)如清單 18 所示:

清單 18. 轉(zhuǎn)換坐標函數(shù)

  
 
 
 
  1. translate(x, y)  x 為橫軸偏移方向大小,y 為縱軸方向偏移大小

其原理如圖所示:

轉(zhuǎn)換坐標

Canvas 繪圖的坐標系和大部分操作系統(tǒng)繪圖的坐標系一致,都是左上角為原點,向右為 x 方向,向下為 y 方向。從圖 5 中我們看出,新的坐標原點平移到了 (x,y) 位置,后面的 Canvas 繪圖函數(shù)都是以新的原點為基準繪圖。清單 17 在繪制每張縮略圖時,首先轉(zhuǎn)換原點到縮略圖的左上角,然后在固定的 x 和 y 坐標位置顯示圖片,將這個過程做成一個循環(huán),就繪制了所有等間距的縮略圖。

將圖片顯示到縮略圖中,我們還需要把圖片縮放到其中較短的一邊能夠和縮略圖的邊長重合,同時截去超出縮略圖大小的圖片部分,從而達到最優(yōu)的顯示縮略圖的效果。其示意圖如所示。

截取最佳圖片部分
 

為了獲得這種最優(yōu)的縮略圖顯示效果,我們需要獲得如下信息:1. 原圖中應(yīng)該截取哪些部分圖片;2 . 縮放多大的比例到目標區(qū)域中。本例定義了函數(shù) getSlicingSrcRect 實現(xiàn)了這個功能,它返回一個 rect 對象,包括了應(yīng)該截取原圖的哪些區(qū)域,其詳細代碼見附件。但還需要一個函數(shù)來將這個截取的圖片部分縮放到目標區(qū)域中,這就用到了 Canvas 繪制圖像函數(shù) drawImage 的另外一種形式:

清單 19. 繪制圖像函數(shù) 3

  
 
 
 
  1. drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)   
  2.  sx, sy, sWidth, sHeight 為原圖中的需要截取的區(qū)域,  dx, dy, dWidth, dHeight 為目標區(qū)域的位置大小

該函數(shù)截取原圖片的部分區(qū)域,然后縮放顯示到目標區(qū)域中。我們利用這個函數(shù),就能夠?qū)崿F(xiàn)截取最佳區(qū)域以顯示在縮略圖中的效果。

在繪制縮略圖我們還實現(xiàn)了一個小技巧:縮略圖大小是固定的,但之間的間距是動態(tài)調(diào)整的,當縮略圖之間的間距小于一個閥值的時候,我們強制最小間隔不小于閥值,詳細代碼請看清單 17。

響應(yīng)點擊事件

顯示縮略圖以后,我們需要響應(yīng)點擊事件,即能夠點擊縮略圖,顯示所對應(yīng)的圖片。同時,我們還需要點擊左右兩邊的按鈕,能夠?qū)崿F(xiàn)縮略圖的翻頁。這是通過清單 20 所示的代碼實現(xiàn)的:

清單 20 . 響應(yīng)鼠標點擊事件

  
 
 
 
  1.    // 加入了鼠標點擊事件的響應(yīng)
  2.    this.load = function() { 
  3.        //event binding 
  4.        canvas.onclick = onMouseClick; 
  5.        canvas.onmousemove = onMouseMove; 
  6. // 鼠標點擊事件處理
  7.    function onMouseClick(event) { 
  8.        point = {x: event.clientX, y:event.clientY}; 
  9.        lastMousePos = point; 
  10.        if (pointIsInRect(point, lButtonRect)) { 
  11.            nextPane(true); 
  12.        } else if (pointIsInRect(point, rButtonRect)) { 
  13.            nextPane(false); 
  14.        } else { 
  15.            var selectedIndex = findSelectImageIndex(point); 
  16.            if (selectedIndex != -1) { 
  17.                selectImage(selectedIndex); 
  18.            } 
  19.        } 
  20.        updateIdleTime(); 
  21.    } 
  22.    // 返回所點擊的縮略圖序號,如果沒有點擊縮略圖則返回 -1 
  23.    function findSelectImageIndex(point) { 
  24.        for(var i = 0; i < imageRects.length; i++) { 
  25.            if (pointIsInRect(point, imageRects[i].rect)) 
  26.                return i + firstImageIndex;        
  27.        return -1; 
  28.    } 
  29.    // 將當前圖片序號設(shè)為 index,重畫
  30.    function selectImage(index) { 
  31.        currentImage = index; 
  32.        paint(); 
  33.    } 
  34.    // 將縮略圖翻頁,更新縮略圖中第一張圖片的序號
  35.    function nextPane(previous) { 
  36.        if (previous) { 
  37.            firstImageIndexfirstImageIndex = firstImageIndex - maxThumbNailCount < 0? 
  38. 0 : firstImageIndex - maxThumbNailCount; 
  39.        } else { 
  40.            firstImageIndexfirstImageIndex = firstImageIndex + maxThumbNailCount*2 - 1 > imageCount - 1? 
  41. (imageCount - maxThumbNailCount > 0? imageCount - maxThumbNailCount: 0) : 
  42. firstImageIndex + maxThumbNailCount; 
  43.            
  44.        } 
  45.        currentImage = (firstImageIndex <= currentImage && 
  46. currentImage <= firstImageIndex + maxThumbNailCount)? currentImage : firstImageIndex; 
  47.        paint(); 
  48.    } 

這里我們通過 2 個變量 firstImageIndex 和 currentImage 來控制縮略圖和當前圖片的顯示,并能夠根據(jù)鼠標點擊來改變當前選中的圖片。


加入其他效果

根據(jù)當前窗口大小調(diào)整 Canvas 大小

當瀏覽器的大小改變的時候,我們的圖片瀏覽器就會由于沒能重畫導(dǎo)致部分區(qū)域無法顯示。我們需要根據(jù)瀏覽器當前頁面大小來動態(tài)定義整個圖片瀏覽器的大小,從而能夠調(diào)整整個圖片瀏覽器的最佳大小。代碼如清單 21 所示:

清單 21 .Resize 支持

  
 
 
 
  1. this.load = function() { 
  2.     //resize 
  3.     resize(); 
  4.     window.onresize = resize; 
  5.     
  6.     //event binding 
  7.     canvas.onclick = onMouseClick; 
  8.     canvas.onmousemove = onMouseMove; 
  9.     loadImages();        
  10.     startLoop(); 
  11.     updateIdleTime(); 
  12. function resize() { 
  13.     var size = getScreenSize(); 
  14.     canvas.width = size.width; 
  15.     canvas.height = size.height; 
  16.     paint(); 
  17. function getScreenSize() { 
  18.     return { width: document.documentElement.clientWidth, 
  19. ght: document.documentElement.clientHeight}; 

這里代碼響應(yīng)了 window 對象的 onresize 事件,從而能夠響應(yīng)整個瀏覽器頁面大小改變的事件,通過 document.documentElement.clientWidth 和 document.documentElement.clientHeight 這兩個 DOM 屬性,我們獲得了當前頁面顯示范圍大小,從而能夠動態(tài)調(diào)整 Canvas 的大小到最佳位置。

顯示縮略圖預(yù)覽

我們還需要實現(xiàn)這種效果:當鼠標放置在某個縮略圖上方時,能夠顯示一個縮略圖預(yù)覽界面,其效果如圖所示:

縮略圖預(yù)覽
 

實現(xiàn)代碼如清單 22 所示:

清單 22 . 縮略圖預(yù)覽代碼

  
 
 
 
  1. const ARROW_HEIGHT = 10;  // 下方三角形的高度
  2. const BORDER_WRAPPER = 2;   // 邊緣白框的厚度
  3. // 繪制預(yù)覽圖
  4. function paintHighLightImage(srcRect, imageRect) { 
  5.   var ratio = imageRect.image.width == srcRect.width? 
  6.   
  7.   THUMBNAIL_LENGTH/imageRect.image.width:THUMBNAIL_LENGTH/imageRect.image.height; 
  8.   ratio *= 1.5; 
  9.     var destRect = { 
  10.         x:imageRect.rect.x + imageRect.rect.width/2 - imageRect.image.width*ratio/2, 
  11.         y:navRect.y - ARROW_HEIGHT - BORDER_WRAPPER - imageRect.image.height*ratio, 
  12.         width: imageRect.image.width * ratio, 
  13.         height: imageRect.image.height * ratio 
  14.     } 
  15.     var wrapperRect = { 
  16.         x: destRect.x - BORDER_WRAPPER, 
  17.         y: destRect.y - BORDER_WRAPPER, 
  18.         width: destRect.width + BORDER_WRAPPER * 2, 
  19.         height: destRect.height + BORDER_WRAPPER * 2 
  20.     } 
  21.     var arrowWidth = ARROW_HEIGHT * Math.tan(30/180*Math.PI); 
  22.     context.save(); 
  23.     context.fillStyle = 'white'; 
  24.     context.translate(wrapperRect.x, wrapperRect.y); 
  25.     context.beginPath(); 
  26.     context.moveTo(0, 0); 
  27.     context.lineTo(wrapperRect.width, 0); 
  28.     context.lineTo(wrapperRect.width, wrapperRect.height); 
  29.     context.lineTo(wrapperRect.width/2 + arrowWidth, wrapperRect.height); 
  30.     context.lineTo(wrapperRect.width/2, wrapperRect.height+ARROW_HEIGHT); 
  31.     context.lineTo(wrapperRect.width/2 - arrowWidth, wrapperRect.height); 
  32.     context.lineTo(0, wrapperRect.height); 
  33.     context.lineTo(0, 0); 
  34.     context.closePath(); 
  35.     context.fill(); 
  36.     context.drawImage(imageRect.image, BORDER_WRAPPER, BORDER_WRAPPER, 
  37. tRect.width, destRect.height); 
  38.     context.restore(); 

在函數(shù) paintHighLightImage 中大量使用了 Canvas 的路徑繪圖函數(shù)來繪制這個底部為三角形箭頭,上部為矩形的形狀。感興趣的讀者可以研究這些 Canvas 繪圖函數(shù)的使用。

自動隱藏

最后我們在加入一個動態(tài)的效果:當鼠標不再移動超過一定時刻的時候,導(dǎo)航欄能夠自動隱藏。其代碼如清單 23 所示:

清單 23 . 自動隱藏代碼

  
 
 
 
  1. // 加入了自動隱藏導(dǎo)航欄的功能
  2.    function paint() { 
  3.        context.clearRect(0, 0, canvas.width, canvas.height); 
  4.        paintImage(currentImage); 
  5.        var paintInfo = {inLeftBtn:false, inRightBtn:false, inThumbIndex: null} 
  6.        if (lastMousePos && navRect && lButtonRect && rButtonRect) { 
  7.            if (pointIsInRect(lastMousePos, navRect)) { 
  8.                paintInfo.inLeftBtn = pointIsInRect(lastMousePos, lButtonRect); 
  9.                paintInfo.inRightBtn = pointIsInRect(lastMousePos, rButtonRect); 
  10.                if (!paintInfo.inLeftBtn && !paintInfo.inRightBtn) { 
  11.                    var index = findSelectImageIndex(lastMousePos); 
  12.                    if (index != -1) { 
  13.                        paintInfo.inThumbIndex = index; 
  14.                    } 
  15.                } 
  16.            } 
  17.        } 
  18.        if(idleTime &
    網(wǎng)站欄目:看HTML5如何創(chuàng)建一個圖片瀏覽器
    分享鏈接:http://www.5511xx.com/article/dhpehgi.html