引入圖像
HTML5 Canvas引入圖像只需要簡(jiǎn)單的兩步:1、首先當(dāng)然是來(lái)源圖片,不是簡(jiǎn)單的 URL 路徑,但可以是一個(gè) JavaScript 的 Image 對(duì)象引用,又或者其它的 canvas 元素,2、用 drawImage
方法將圖像插入到 canvas 中。
先來(lái)看看第1步,基本上有四種可選方式:
引用頁(yè)面內(nèi)的圖片
這可以通過(guò) document.images
集合和document.getElementsByTagName
方法又或者 document.getElementById
方法來(lái)獲取頁(yè)面內(nèi)的圖片(如果已知圖片元素的 ID)。
使用其它 canvas 元素 Using other canvas elements
和引用頁(yè)面內(nèi)的圖片類(lèi)似地,用 document.getElementsByTagName
或 document.getElementById
方法來(lái)獲取其它 canvas 元素。但你引入的應(yīng)該是已經(jīng)準(zhǔn)備好的 canvas。
由零開(kāi)始創(chuàng)建圖像
另外,我們可以用腳本創(chuàng)建一個(gè)新的 Image
對(duì)象,但這種方法的主要缺點(diǎn)是如果不希望腳本因?yàn)榈却龍D片裝置而暫停,還得需要突破預(yù)裝載。
我們可以通過(guò)下面簡(jiǎn)單的方法來(lái)創(chuàng)建圖片:
var img = new Image(); // Create new Image object img.src = 'myImage.png'; // Set source path
當(dāng)腳本執(zhí)行后,圖片開(kāi)始裝載。若調(diào)用 drawImage
時(shí),圖片沒(méi)裝載完,腳本會(huì)等待直至裝載完畢。如果不希望這樣,可以使用 onload
事件:
var img = new Image(); // Create new Image object img.onload = function(){ // execute drawImage statements here } img.src = 'myImage.png'; // Set source path
如果你只用到一張圖片的話,這已經(jīng)夠了。但一旦需要不止一張圖片,那就需要更加復(fù)雜的處理方法,但圖片預(yù)裝載策略超出本教程的范圍,感興趣的話可以參考JavaScript Image Preloader。
通過(guò) data: url 方式嵌入圖像
我們還可以通“Data:_URL”方式來(lái)引用圖像。Data urls 允許用一串 Base64 編碼的字符串的方式來(lái)定義一個(gè)圖片。其優(yōu)點(diǎn)就是圖片內(nèi)容即時(shí)可用,無(wú)須再到服務(wù)器兜一圈。(還有一個(gè)優(yōu)點(diǎn)是,可以將 CSS,JavaScript,HTML 和 圖片全部封裝在一起,遷移起來(lái)十分方便。)缺點(diǎn)就是圖像沒(méi)法緩存,圖片大的話內(nèi)嵌的 url 數(shù)據(jù)會(huì)相當(dāng)?shù)拈L(zhǎng):
var img_src = 'data:image/gif;base64,R0lGODlhCwALAIAAAAAA3pn/ZiH5BAEAAAEALAAAAAALAAsAAAIUhA+hkcuO4lmNVindo7qyrIXiGBYAOw==';
drawImage
一旦獲得了源圖對(duì)象,我們就可以使用 drawImage
方法將它渲染到 canvas 里。drawImage
方法有三種形態(tài),下面是最基礎(chǔ)的一種。
drawImage(image, x, y)
其中 image
是 image 或者 canvas 對(duì)象,x
和 y 是其在目標(biāo) canvas 里的起始坐標(biāo)。
drawImage
示例 1
下面一個(gè)例子我用一個(gè)外部圖像作為一線性圖的背景。用背景圖我們就不需要繪制負(fù)責(zé)的背景,省下不少代碼。這里只用到一個(gè) image 對(duì)象,于是就在它的
onload
事件響應(yīng)函數(shù)中觸發(fā)繪制動(dòng)作。drawImage
方法將背景圖放置在 canvas 的左上角(0,0) 處。
function draw() { var ctx = document.getElementById('canvas').getContext('2d'); var img = new Image(); img.onload = function(){ ctx.drawImage(img,0,0); ctx.beginPath(); ctx.moveTo(30,96); ctx.lineTo(70,66); ctx.lineTo(103,76); ctx.lineTo(170,15); ctx.stroke(); } img.src = 'images/backdrop.png'; }
縮放
drawImage
方法的又一變種是增加了兩個(gè)用于控制圖像在 canvas 中縮放的參數(shù)。
drawImage(image, x, y, width, height)
Where width
and height
is the image's size on the target canvas. 當(dāng)中 width
和 height
分別是圖像在 canvas 中顯示大小。
drawImage
示例 2
在這個(gè)例子里,我會(huì)用一張圖片像背景一樣在 canvas 中以重復(fù)平鋪開(kāi)來(lái)。實(shí)現(xiàn)起來(lái)也很簡(jiǎn)單,只需要循環(huán)鋪開(kāi)經(jīng)過(guò)縮放的圖片即可。見(jiàn)下面的代碼,第一層
for
循環(huán)是做行重復(fù),第二層是做列重復(fù)的。圖像大小被縮放至原來(lái)的三分之一,50x38 px。這種方法可以用來(lái)很好的達(dá)到背景圖案的效果,在下面的教程中會(huì)看到。
注意:圖像可能會(huì)因?yàn)榇蠓鹊目s放而變得起雜點(diǎn)或者模糊。如果您的圖像里面有文字,那么最好還是不要進(jìn)行縮放,因?yàn)槟菢犹幚碇蠛芸赡軋D像里的文字就會(huì)變得無(wú)法辨認(rèn)了。
function draw() { var ctx = document.getElementById('canvas').getContext('2d'); var img = new Image(); img.onload = function(){ for (i=0;i<4;i++){ for (j=0;j<3;j++){ ctx.drawImage(img,j*50,i*38,50,38); } } } img.src = 'images/rhino.jpg'; }
切片 Slicing
drawImage
方法的第三個(gè)也是最后一個(gè)變種有8個(gè)新參數(shù),用于控制做切片顯示的。
drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
第一個(gè)參數(shù)和其它的是相同的,都是一個(gè)圖像或者另一個(gè) canvas 的引用。其它8個(gè)參數(shù)最好是參照右邊的圖解,前4個(gè)是定義圖像源的切片位置和大小,后4個(gè)則是定義切片的目標(biāo)顯示位置和大小。
切片是個(gè)做圖像合成的強(qiáng)大工具。假設(shè)有一張包含了所有元素的圖像,那么你可以用這個(gè)方法來(lái)合成一個(gè)完整圖像。例如,你想畫(huà)一張圖表,而手上有一個(gè)包含所有必需的文字的 PNG 文件,那么你可以很輕易的根據(jù)實(shí)際數(shù)據(jù)的需要來(lái)改變最終顯示的圖表。這方法的另一個(gè)好處就是你不需要單獨(dú)裝載每一個(gè)圖像。
drawImage
示例 3
在這個(gè)例子里面我用到上面已經(jīng)用過(guò)的犀牛圖像,不過(guò)這次我要給犀牛頭做個(gè)切片特寫(xiě),然后合成到一個(gè)相框里面去。相框帶有陰影效果,是一個(gè)以 24-bit PNG 格式保存的圖像。因?yàn)?24-bit PNG 圖像帶有一個(gè)完整的 8-bit alpha 通道,與 GIF 和 8-bit PNG 不同,我可以將它放成背景而不必?fù)?dān)心底色的問(wèn)題。
我用一個(gè)與上面用到的不同的方法來(lái)裝載圖像,直接將圖像插入到 HTML 里面,然后通過(guò) CSS 隱藏(display:none
)它。兩個(gè)圖像我都賦了 id
,方便后面使用。看下面的腳本,相當(dāng)簡(jiǎn)單,首先對(duì)犀牛頭做好切片(第一個(gè) drawImage
)放在 canvas 上,然后再上面套個(gè)相框(第二個(gè) drawImage
)。
function draw() { var canvas = document.getElementById('canvas'); var ctx = canvas.getContext('2d'); // Draw slice ctx.drawImage(document.getElementById('source'), 33,71,104,124,21,20,87,104); // Draw frame ctx.drawImage(document.getElementById('frame'),0,0); }
示例:畫(huà)廊 Art gallery example![\" src=]()
我這一章最后的示例是弄一個(gè)小畫(huà)廊。畫(huà)廊由掛著幾張畫(huà)作的格子組成。當(dāng)頁(yè)面裝載好之后,為每張畫(huà)創(chuàng)建一個(gè) canvas 元素并用加上畫(huà)框然后插入到畫(huà)廊中去。
在我這個(gè)例子里面,所有“畫(huà)”都是固定寬高的,畫(huà)框也是。你可以做些改進(jìn),通過(guò)腳本用畫(huà)的寬高來(lái)準(zhǔn)確控制圍繞它的畫(huà)框的大小。
下面的代碼應(yīng)該是蠻自我解釋的了。就是遍歷圖像對(duì)象數(shù)組,依次創(chuàng)建新的 canvas 元素并添加進(jìn)去。可能唯一需要注意的,對(duì)于那些并不熟悉 DOM 的朋友來(lái)說(shuō),是 insertBefore 方法的用法。insertBefore
是父節(jié)點(diǎn)(單元格)的方法,用于將新節(jié)點(diǎn)(canvas 元素)插入到我們想要插入的節(jié)點(diǎn)之前。
function draw() { // Loop through all images for (i=0;i<document.images.length;i++){ // Don't add a canvas for the frame image if (document.images[i].getAttribute('id')!='frame'){ // Create canvas element canvas = document.createElement('CANVAS'); canvas.setAttribute('width',132); canvas.setAttribute('height',150); // Insert before the image document.images[i].parentNode.insertBefore(canvas,document.images[i]); ctx = canvas.getContext('2d'); // Draw image to canvas ctx.drawImage(document.images[i],15,20); // Add frame ctx.drawImage(document.getElementById('frame'),0,0); } } }
控制圖像的縮放行為
Introduced in Gecko 1.9.2
(Firefox 3.6 / Thunderbird 3.1 / Fennec 1.0)Gecko 1.9.2 引入了 mozImageSmoothingEnabled
屬性,值為 false
時(shí),圖像不會(huì)平滑地縮放。默認(rèn)是 true
。
cx.mozImageSmoothingEnabled = false;
HTML5 canvas 元素詳細(xì)教程三之應(yīng)用圖像,希望對(duì)大家有用。