版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、HTML5資料-非常好1 Canvas教程是一個新的用于通過腳本(通常是JavaScript)繪圖的HTML元素。例如,他可以用于繪圖、制作圖片的組合或者簡單的動畫(當(dāng)然并不那么簡單)。It can for in sta nee beused to draw graphs, make photo compositi ons or do simple (and not so simple)ani mati ons.1.1基本用法元素讓我們從元素的定義開始吧??雌饋砗芟?,唯一不同就是它不含src和alt屬性。它只有兩個屬性,width和height,兩個都是可選的,并且都可以DOM或者CSS來設(shè)置
2、。如果不指定width和height,默認的是寬300像素,高150像素。雖然可以通過CSS來調(diào)整canvas的大小,但渲 染圖像會縮放來適應(yīng)布局的(如果你發(fā)現(xiàn)渲染結(jié)果看上去變形了,不必一味依賴CSS可以嘗試顯式指定canvas的width和height屬性值)。id屬性不是專享的,就像標(biāo)準的HTLM標(biāo)簽一樣,任何一個HTML元素都可以指定其id值。一般,為元素指定id是個不錯的主意,這樣使得在腳本中應(yīng)用更加方便。元素可以像普通圖片一樣指定其樣式(邊距,邊框,背景等等)。然而這些樣式并不 會對canvas實際生成的圖像產(chǎn)生什么影響。下面我們會看到如何應(yīng)用樣式。如果不指定樣 式,canvas默認
3、是全透明的。替用內(nèi)容因為相對較新,有些瀏覽器并沒實現(xiàn),如Firefox 1.0和In ternet Explorer,所以我們需要為那些不支持canvas的瀏覽器提供替用顯示內(nèi)容。我們只需要直接在canvas元素內(nèi)插入替用內(nèi)容即可。不支持canvas的瀏覽器會忽略canvas元素而直接渲染替用內(nèi)容,而支持的瀏覽器則會正常地渲染canvas。例如,我們可以把一些文字或圖片填入canvas內(nèi),作為替用內(nèi)容:curre nt stock price: $3.15 +0.15結(jié)束標(biāo)簽是必須的 在Apple Safari里,的實現(xiàn)跟很相似,它并不沒有結(jié)束標(biāo)簽。然而,為了使能在web的世界里廣泛適用,需要
4、給替用內(nèi)容提供一個容身之所,因此,在Mozilla的實現(xiàn)里結(jié)束標(biāo)簽()是必須的。如果沒有替用內(nèi)容,Safari會簡單地忽略結(jié)束標(biāo)簽。如果有替用內(nèi)容,那么可以用一些CSS技巧來為并且僅為Safari替用內(nèi)容是需要在IE里顯示但不需要在Safari里顯示。渲染上下文(Ren deri ng Con text)創(chuàng)建的固定尺寸的繪圖畫面開放了一個或多個渲染上下文(ren deri ng con text),我們可以通過它們來控制要顯示的內(nèi)容。我們專注于2D渲染上,這也是目前唯一的選擇,可能在將來會添加基于OpenGL ES的3D上下文。初始化是空白的,要在上面用腳本畫圖首先需要其渲染上下文(rende
5、ringcon text),它可以通過canvas元素對象的getCo ntext方法來獲取,同時得到的還有一些畫圖用的函數(shù)。getCo ntext()接受一個用于描述其類型的值作為參數(shù)。var can vas = docume nt.getEleme ntByld(tutorial);var ctx = can vas.getC on text(2d);上面第一行通過getElementByld方法取得canvas對象的DOM節(jié)點。然后通過其getCo ntext方法取得其畫圖操作上下文。檢查瀏覽器的支持除了在那些不支持的瀏覽器上顯示替用內(nèi)容,還可以通過腳本的方式來檢查瀏覽器是否支持canv
6、as。方法很簡單,判斷getCo ntext是否存在即可。var can vas = docume nt.getEleme ntByld(tutorial);if (ca nvas.getC on text)var ctx = can vas.getC on text(2d);/ draw ing code here else / can vas-un supported code here代碼模板我們會用下面這個最簡化的代碼模板來(后續(xù)的示例需要用到)作為開始,你可以 到本地備用。對Safari和Mozilla是完全兼容的隱藏替用內(nèi)容,因為那些下載文件Ca nvas tutorialvscr
7、ipt type=text/javascriptfun cti on draw()var can vas = docume nt.getEleme ntByld(tutorial);if (ca nvas.getC on text)var ctx = can vas.getC on text(2d);can vas border: 1px solid black; 細心的你會發(fā)現(xiàn)我準備了一個名為draw的函數(shù),它會在頁面裝載完畢之后執(zhí)行一次(通過設(shè)置body標(biāo)簽的onload屬性),它當(dāng)然也可以在setTimeout,setInterval,或者其他事件處理函數(shù)中被調(diào)用。一個簡單的例子作為開始
8、,來一個簡單的吧-繪制兩個交錯的矩形,其中一個是有alpha透明效果。我們會在后面的示例中詳細的讓你了解它是如何運作的。觀看示例fun ctio n draw() var can vas = docume nt.getEleme ntByld(ca nvas);if (ca nvas.getC on text) var ctx = can vas.getC on text(2d);ctx.fillStyle = rgb(200,0,0);ctx.fillRect (10, 10, 55, 50);ctx.fillStyle = rgba(0, 0, 200, 0.5);ctx.fillRect
9、 (30, 30, 55, 50);vcanvas id=ca nvas width=150 height=1501.2繪圖Draw ing shapes繪制圖形網(wǎng)格The grid在真正開始之前,我們需要先探討canvas的網(wǎng)格(grid)或者坐標(biāo)空間(coordinatespace)。在前一頁的HTML模板里有一個150像素寬,150像素高的canvas對象。我在畫 面上疊加上默認網(wǎng)格,如右圖。通常網(wǎng)格的1個單元對應(yīng)canvas上的1個像素。網(wǎng)格的原點是定位在左上角(坐標(biāo)(0,0)。畫面里的所有物體的位置都是相對這個原點。這樣,左上角 的藍色方塊的位置就是距左邊x像素和距上邊Y像素(坐標(biāo)(
10、x, y)。后面的教程中我們將學(xué)會如何把移動原點,旋轉(zhuǎn)以及縮放網(wǎng)格。不過現(xiàn)在我們會使用默認的狀態(tài)。繪制圖形Drawing shapes不像SVG, canvas只支持一種基本形狀-矩形,所以其它形狀都是有一個或多個路徑組合而成。還好,有一組路徑繪制函數(shù)讓我們可以繪制相當(dāng)復(fù)雜的形狀。矩形Rectan gles我們首先看看矩形吧,有三個函數(shù)用于繪制矩形的:fillRect(x,y,width,height) : Draws a filled rectangle strokeRect(x,y,width,height): Draws a rectangularoutlineclearRect(x,y
11、,width,height) : Clears the specified area and makes it fully tran spare nt它們都接受四個參數(shù),x和y指定矩形左上角(相對于原點)的位置,width和height是矩形的寬和高。好,實戰(zhàn)一下吧。下面就是上頁模板里的draw()函數(shù),但添加了上面的三個函數(shù)。繪制矩形的例子Rectan gular shape example觀看示例fun ctio n draw()var can vas = docume nt.getEleme ntByld(tutorial);if (ca nvas.getC on text)var ct
12、x = can vas.getC on text(2d);ctx.fillRect(25,25,100,100);ctx.clearRect(45,45,60,60);ctx.strokeRect(50,50,50,50);出來的結(jié)果應(yīng)該和右邊的是一樣的。fillRect函數(shù)畫了一個大的黑色矩形(100 x100),clearRect函數(shù)清空了中間60 x60大小的方塊,然后strokeRect函數(shù)又在清空了的空間內(nèi)勾勒出一個50 x50的矩形邊框。在接下去的頁面里,我們會看到和clearRect函數(shù)差不多另外兩個方法,以及如何去改變圖形的填充和邊框顏色。與下一節(jié)的路徑函數(shù)不一樣,這三個函數(shù)的
13、效果會立刻在canvas上反映出來。繪制路徑Drawing paths不像畫矩形那樣的直截了當(dāng),繪制路徑是需要一些額外的步驟的。begi nPath()closePath() stroke()fill()第一步是用beginPath創(chuàng)建一個路徑。在內(nèi)存里,路徑是以一組子路徑(直線,弧線等)的形式儲存的,它們共同構(gòu)成一個圖形。每次調(diào)用beginPath,子路徑組都會被重置,然后可以繪制新的圖形。第二步就是實際繪制路徑的部分,很快我們就會看到。第三步是調(diào)用closePath方法,它會嘗試用直線連接當(dāng)前端點與起始端點來關(guān)閉路徑,但如果圖形已經(jīng)關(guān)閉或者只有一個點,它會什么都不做。這一步不是必須的。最后
14、一步是調(diào)用stroke或fill方法,這時,圖形才是實際的繪制到canvas上去。stroke是繪制圖形的邊框,fill會用填充出一個實心圖形。注意:當(dāng)調(diào)用fill時,開放的路徑會自動閉合,而無須調(diào)用closePath。畫一個簡單圖形(如三角形)的代碼如下。ctx.beg in Path();ctx.moveTo(75,50);ctx.li neTo(100,75);ctx.li neTo(100,25);ctx.fill();moveTo是一個十分有用的方法,雖然并不能用它來畫什么,但卻是繪制路徑的實用方法的一 部分。你可以把它想象成是把筆提起,并從一個點移動到另一個點的過程。moveTo(
15、x, y)它接受x和y(新的坐標(biāo)位置)作為參數(shù)。當(dāng)canvas初始化或者調(diào)用beginPath的時候,起始坐標(biāo)設(shè)置就是原點(0,0)。大多數(shù)情況下,我們用moveTo方法將起始坐標(biāo)移至其它地方,或者用于繪制不連續(xù)的路徑??纯从疫叺?笑臉,紅線就是使用moveTo移動的軌跡。試一試下面的代碼,粘貼到之前用過的draw函數(shù)內(nèi)在看看效果吧。moveTo的使用示例觀看示例ctx.beg in Path();ctx.arc(75,75,50,0,Math .P l*2,true); / Outer circlectx.moveTo(110,75);ctx.arc(75,75,35,0,Math.PI,f
16、alse);/ Mouth (clockwise)ctx.moveTo(65,65);ctx.arc(60,65,5,0,Math.PI*2,true);ctx.moveTo(95,65);/ Left eyectx.arc(90,65,5,0,Math.PI*2,true);ctx.stroke();/ Right eye/thego neheart完整例子ctx.beginPath();ctx.arc(75,75,50,0,Math. PI*2,true); / Outer circlectx.moveTo(110,75);ctx.arc(75,75,35,0,Math.PI,false)
17、;/ Mouth (clockwise)ctx.moveTo(65,65);ctx.arc(60,65,5,0,Math.PI*2,true);/ Left eyectx.moveTo(95,65);ctx.arc(90,65,5,0,Math.PI*2,true);/ Right eyectx.stroke();ctx.beg in Path();ctx.moveTo(40,75);ctx.li neTo(60,65);ctx.li neTo(90,65);ctx.moveTo(110,75);ctx.li neTo(125,75);ctx.stroke();注意:你可以注釋moveTo方法
18、來觀察那些連接起來的線。注意:arc方法的用法見下面。繪制各種線條Lines我們用lineTo方法來畫直線。lin eTo(x, y)lineTo方法接受終點的坐標(biāo)(x,y)作為參數(shù)。起始坐標(biāo)取決于前一路徑,前一路徑的終點 即當(dāng)前路徑的起點,起始坐標(biāo)也可以通過moveTo方法來設(shè)置。lin eTo的使用示例示例(如右圖)畫的是兩個三角形,一個實色填充,一個勾邊。首先調(diào)用begi nPath方法創(chuàng)建一個新路徑,然后用moveTo方法將起始坐標(biāo)移至想要的位置,然后畫兩條直線來構(gòu)成三角形的兩條邊??梢宰⒁獾絝ill和strok繪三角形的區(qū)別,上面也提到過,使用fill路徑會自動閉合,但使用strok
19、e不會,如果不關(guān)閉路徑,勾畫出來的只有兩邊。觀看示例/填充三角形ctx.beg in Path();ctx.moveTo(25,25);ctx.li neTo(105,25);ctx.li neTo(25,105);ctx.fill();/勾邊三角形ctx.beg in Path();ctx.moveTo(125,125);ctx.li neTo(125,45);ctx.li neTo(45,125);ctx.closePath();ctx.stroke();弧線Arcs我們用arc方法來繪制弧線或圓。標(biāo)準說明中還包含arcTo方法,當(dāng)前Safari是支持的,但基于Gecko的瀏覽器還未實現(xiàn)。
20、arc(x, y, radius, startA ngle, endAn gle, an ticlockwise)方法接受五個參數(shù):x,y是圓心坐標(biāo),radius是半徑,startAngle和endAngle分別是起 末弧度(以x軸為基準),anticlockwise為true表示逆時針,反之順時針。警告:在Firefox的beta版本里,最后一個參數(shù)是clockwise,而最終版本不是。因此如果是從beta升級至發(fā)行版需要做相應(yīng)修改。注意:arc方法里用到的角度是以弧度為單位而不是度。度和弧度直接的轉(zhuǎn)換可以用這個表達式:var radians = (Math.PI/180)*degrees;
21、。arc的使用示例這個示例比之前見到過的要復(fù)雜一些,畫了12個不同的弧形,有不同夾角和填充狀態(tài)的。如果我用上面畫笑臉的方式來畫這些弧形,那會是一大段的代碼,而且,畫每一個弧形時我都需var x=25+j*50; / x coordi nate要知道其圓心位置。像我這里畫90,180和270度的弧形看起來不是很麻煩,但是如果圖形更復(fù)雜一些,則實現(xiàn)起來會越來越困難。這里使用兩個for循環(huán)來畫多行多列的弧形。每一個弧形都用beginPath方法創(chuàng)建一個新路徑。然后為了方便閱讀和理解,我把所有參數(shù)都寫成變量形式。顯而易見,x和y作為圓心坐標(biāo)。radius和startAngle都是固定,endAngle
22、從180度半圓開始,以90度方式遞增至圓。anticlockwise則取決于奇偶行數(shù)。最后,通過if語句判斷使前兩行表現(xiàn)為勾邊,而后兩行為填充效果。觀看示例=25+j*50; / x coordi nate=25+i*50; / y coordi nate=20; / Arc radius=0; / Start ing point on circle=Math.PI+(Math.PI*j)/2;/ End poi nt on=i%2=0 ? false : true; / clockwise or an ticlockwisectx.arc(x,y,radius,startA ngle,e n
23、dAn gle, an ticlockwise);if (i1)ctx.fill(); else ctx.stroke();/chinese_xu原始代碼并沒有按照1/4圓遞增來畫。/修改后輸出4行4列,要把畫布擴大到200*200觀看for (i=0;i4;i+)for(j=0;j4;j+)ctx.beg in Path();for(i=0;i4;i+) for(j=0;j1)ctx.fill(); else ctx.stroke();貝塞爾和二次方曲線Bezier and quadratic curves接下來要介紹的路徑是貝塞爾曲線,它可以是二次和三次方的形式,一般用于繪制復(fù)雜而有規(guī)律的
24、形狀。quadraticCurveTo(cp1x, cp1y, x, y) / BROKEN in Firefox 1.5 (see work around below)bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)上面兩行代碼的區(qū)別見右圖。它們都有一個起點一個終點(圖中的藍點),但二次方貝塞爾曲 線只有一個(紅色)控制點點)而三次方貝塞爾曲線有兩個。參數(shù)x和y是終點坐標(biāo),cplx和cply是第一個控制點的坐標(biāo),cp2x和cp2y是第二個的。使用二次方和三次方的貝塞爾曲線是相當(dāng)有挑戰(zhàn)的,因為不像在矢量繪圖軟件AdobeIllustrator里那樣有即時的
25、視覺反饋。因為用它來畫復(fù)雜圖形是比較麻煩的。但如果你有時間,并且最重要是有耐心,再復(fù)雜的圖形都可以繪制出來的。下面我們來畫一個簡單而又規(guī)律 的圖形。這些例子都比較簡單。我們繪制的都是完整的圖形。quadraticCurveTo的使用示例var radiusvar startA nglevar endAn glevar an ticlockwise查看示例/ Quadratic curves examplectx.beg in Path();ctx.moveTo(75,25);ctx.quadraticCurveTo(25,25,25,62.5);ctx.quadraticCurveTo(25,
26、100,50,100);ctx.quadraticCurveTo(50,120,30,125);ctx.quadraticCurveTo(60,120,65,100);ctx.quadraticCurveTo(125,100,125,62.5);ctx.quadraticCurveTo(125,25,75,25);ctx.stroke();通過計算,可以由二次曲線的單個控制點得出相應(yīng)三次方曲線的兩個控制點,因此二次方轉(zhuǎn)三 次方是可能的,但是反之不然。僅當(dāng)三次方程中的三次項為零是才可能轉(zhuǎn)換為二次的貝塞爾曲 線。通常地可以用多條二次方曲線通過細分算法來近似模擬三次方貝塞爾曲線。bezierCurv
27、eTo的使用示例查看示例/ Bezier curves examplectx.beg in Path();ctx.moveTo(75,40);ctx.bezierCurveTo(75,37,70,25,50,25);ctx.bezierCurveTo(20,25,20,62.5,20,62.5);ctx.bezierCurveTo(20,80,40,102,75,120);ctx.bezierCurveTo(110,102,130,80,130,62.5);ctx.bezierCurveTo(130,62.5,130,25,100,25);ctx.bezierCurveTo(85,25,75,
28、37,75,40);ctx.fill();Firefox 1.5 quadraticCurveTo() bug的應(yīng)對方案在Firefox 1.5里,quadatricCurveTo()的實現(xiàn)是有bug的,它不是直接繪制二次方曲線,而是調(diào)用bezierCurveTo(),其中兩個控制點都是二次方曲線的那個單控制點。因此,它會繪制出不正確的曲線。如果必須使用到quadraticCurveTo(),你需要自行去將二次方曲線轉(zhuǎn)換成三次方的,這樣就可以用bezierCurveTo()方法了。var curre ntX, curre ntY;/ set to last x,y sent to lin eT
29、o/moveTo/bezierCurveToor quadraticCurveToFixed()function quadraticCurveToFixed( cpx, cpy, x, y ) /*For the equatio ns below the followi ng variable n ame prefixes are used:qp0 is the quadratic curve start ing poin t (you must keep this from yourlast point sent to moveTo(), li neTo(), or bezierCurveT
30、o().qp1 is the quadatric curve con trol poin t (this is the cpx,cpy you would have sent toquadraticCurveTo().qp2 is the quadratic curve ending poin t (this is the x,y argume nts you would have sent toquadraticCurveTo().We will convert these poi nts to compute the two n eeded cubic con trol poi nts(t
31、he start ing/ending points are the same for boththe quadratic and cubic curves.The equati ons for the two cubic con trol points are:cp0=qp0 and cp3=qp2cp1 = qp0 + 2/3 *(qp1-qp0)cp2 = cp1 + 1/3 *(qp2-qp0)In the code below, we must compute both the x and y terms for each point separately.cplx = qp0 x
32、+ 2.0/3.0*(qp1x - qpOx);cply = qp0y + 2.0/3.0*(qp1y - qp0y);cp2x = cplx + (qp2x - qp0 x)/3.0;cp2y = cply + (qp2y - qp0y)/3.0;We will nowa) replace the qp0 x and qp0y variables with curre ntX and curre ntY (which *you* must store foreach moveTo/l in eTo/bezierCurveTo)b) replace the qplx and qply vari
33、ables with cpx and cpy (which we would have passed toquadraticCurveTo)c) replace the qp2x and qp2y variables with x and y.which leaves us with:*/var cplx = curre ntX + 2.0/3.0*(cpx - curre ntX);var cply = curre ntY + 2.0/3.0*(cpy - curre ntY);var cp2x = cplx + (x - curre ntX)/3.0;var cp2y = cply + (
34、y - curre ntY)/3.0;/ and now call cubic Bezier curve to functionbezierCurveTo( cp1x, cp1y, cp2x, cp2y, x, y );curre ntX = x;curre ntY = y;矩形路徑Rectangles除了上面提到的三個方法可以直接繪制矩形之外,我們還有一個rect方法是用于繪制矩形路徑的。rect(x, y, width, height)它接受四個參數(shù),x和y是其左上角坐標(biāo),width和height是其寬和高。當(dāng)它被調(diào)用時,moveTo方法會自動被調(diào)用,參數(shù)為(0,0),于是起始坐標(biāo)又恢復(fù)成
35、初始原點 了。綜合Making comb in ati ons上面所用到的例子都只用到了一種類型的路徑,當(dāng)然canvas不會限制所使用的路徑類型的多少。所以,我們來看一個路徑大雜燴。綜合樣例在整個例子里,最值得注意的是roun dedRect函數(shù)的使用和fillStyle屬性的設(shè)置。自定義函數(shù)對于封裝復(fù)雜圖形的繪制是非常有用的。在這個例子里使用自定義函數(shù)就省掉了大約一半 的代碼。在接下來的例子里會深入探討fillStyle屬性的使用。這里是用它來改變填充顏色,從默認的黑色,到白色,然后再回到黑色。查看示例fun ctio n draw() var ctx = docume nt.getElem
36、e ntByld(ca nvas).getC on text(2d);rou ndedRect(ctx,12,12,150,150,15);rou ndedRect(ctx,19,19,150,150,9);rou ndedRect(ctx,53,53,49,33,10);rou ndedRect(ctx,53,119,49,16,6);rou ndedRect(ctx,135,53,49,33,10);rou ndedRect(ctx,135,119,25,49,10);ctx.begi nPath();ctx.arc(37,37,13,Math.PI/7,-Math.PI/7,false)
37、; /chiensexu了ctx.li neTo(31,37);ctx.fill();for(i=0;i8;i+)ctx.fillRect(51+i*16,35,4,4);for(i=0;i6;i+)ctx.fillRect(115,51+i*16,4,4);for(i=0;i8;i+)ctx.fillRect(51+i*16,99,4,4);ctx.begi nPath();ctx.moveTo(83,116);ctx.li neTo(83,102);ctx.bezierCurveTo(83,94,89,88,97,88);ctx.bezierCurveTo(105,88,111,94,11
38、1,102);ctx.li neTo(111,116);ctx.li neTo(106.333,111.333);ctx.li neTo(101.666,116);ctx.li neTo(97,111.333);ctx.li neTo(92.333,116);ctx.li neTo(87.666,111.333);ctx.li neTo(83,116);ctx.fill();ctx.fillStyle = white;ctx.begi nPath();ctx.moveTo(91,96);ctx.bezierCurveTo(88,96,87,99,87,101);ctx.bezierCurveT
39、o(87,103,88,106,91,106);本來是true呵呵,反ctx.bezierCurveTo(94,106,95,103,95,101);ctx.bezierCurveTo(95,99,94,96,91,96);ctx.moveTo(103,96);ctx.bezierCurveTo(100,96,99,99,99,101);ctx.bezierCurveTo(99,103,100,106,103,106);ctx.bezierCurveTo(106,106,107,103,107,101);ctx.bezierCurveTo(107,99,106,96,103,96);ctx.f
40、ill();ctx.fillStyle = black;ctx.begi nPath();ctx.arc(101,102,2,0,Math.PI*2,true);ctx.fill();ctx.begi nPath();ctx.arc(89,102,2,0,Math. PI*2,true);ctx.fill();function roun dedRect(ctx,x,y,width,height,radius)ctx.begi nPath();ctx.moveTo(x,y+radius);ctx.li neTo(x,y+height-radius);ctx.quadraticCurveTo(x,
41、y+height,x+radius,y+height);ctx.lin eTo(x+width-radius,y+height);ctx.quadraticCurveTo(x+width,y+height,x+width,y+height-radius);ctx.lin eTo(x+width,y+radius);ctx.quadraticCurveTo(x+width,y,x+width-radius,y);ctx.li neTo(x+radius,y);ctx.quadraticCurveTo(x,y,x,y+radius);ctx.stroke();1.3使用圖像應(yīng)用圖像Using im
42、agesCanvas相當(dāng)有趣的一項功能就是可以引入圖像,它可以用于圖片合成或者制作背景等。而目前僅可以在圖像中加入文字(標(biāo)準說明中并沒有包含繪制文字的功能)。只要是Gecko支持的圖像(如PNG, GIF,JPEG等)都可以引入到canvas中,而且其它的canvas元素也可以 作為圖像的來源。弓I入圖像Importing images引入圖像只需要簡單的兩步:第一當(dāng)然是來源圖片,不是簡單的URL路徑,但可以是一個JavaScript的Image對象引用,又或者其它的canvas元素。然后用drawImage方法將圖像插入到canvas中。先來看看第一步,基本上有四種可選方式:弓丨用頁面內(nèi)的圖
43、片Using images which are on the same page我們可以通過document.images集合、document.getElementsByTagName方法又或者document.getElementByld方法來獲取頁面內(nèi)的圖片(如果已知圖片元素的ID。使用其它canvas元素Using other canvas elements和引用頁面內(nèi)的圖片類似地,用docume nt.getEleme ntsByTagName或docume nt.getEleme ntByld方法來獲取其它canvas元素。但你引入的應(yīng)該是已經(jīng)準備好的canvas。一個常用的應(yīng)用就
44、是為另一個大的canvas做縮略圖。由零開始創(chuàng)建圖像Creat ing an image from scratch另外,我們可以用腳本創(chuàng)建一個新的Image對象,但這種方法的主要缺點是如果不希望腳本因為等待圖片裝置而暫停,還得需要突破預(yù)裝載。我們可以通過下面簡單的方法來創(chuàng)建圖片:view pla inprint?var img = new Image();img.src = mylmage.p ng:/ Set source path當(dāng)腳本執(zhí)行后,圖片開始裝載。若調(diào)用drawlmage時,圖片沒裝載完,腳本會等待直至裝載完畢。如果不希望這樣,可以使用onl oad事件:view pla inp
45、rint?var img = new lmage();/ Create new Image objectimg.o nload = fun ctio n()/ execute drawImage stateme nts here/ Create new Image objectimg.src = myImage.p ng:/ Set source path如果你只用到一張圖片的話,這已經(jīng)夠了。但一旦需要不止一張圖片,那就需要更加復(fù)雜的處 理方法,但圖片預(yù)裝載策略超出本教程的范圍,感興趣的話可以參考JavaScript ImagePreloader。通過data: url方式嵌入圖像Embedd
46、ing an image via data: url我們還可以通過data: url方式來引用圖像。Data urls允許用一串Base64編碼的字符串的方式來定義一個圖片。 其優(yōu)點就是圖片內(nèi)容即時可用, 無須再到服務(wù)器兜一圈。 (還有一個 優(yōu)點是, 可以將CSS,JavaScript,HTML和圖片全部封裝在一起,遷移起來十分方便。)缺 點就是圖像沒法緩存,圖片大的話內(nèi)嵌的url數(shù)據(jù)會相當(dāng)?shù)拈L:view pla inprint?var img_src =data:image/gif;base64,ROIGODIhCwALAIAAAAAA3p n/ZiH5BAEAAAEALAAAAAALAAs
47、AAAIUhA+hkcu04lmNVi ndo7qyrlXiGBYAOw=:drawImage一旦獲得了源圖對象,我們就可以使用drawImage方法將它渲染到canvas里。drawImage方法有三種形態(tài),下面是最基礎(chǔ)的一種。drawImage(image, x, y)其中image是image或者canvas對象,x和y是其在目標(biāo)canvas里的起始坐標(biāo)。drawImage示例1下面一個例子我用一個外部圖像作為一線性圖的背景。用背景圖我們就不需要繪制負責(zé)的背景,省下不少代碼。這里只用到一個image對象,于是就在它的on load事件響應(yīng)函數(shù)中觸發(fā)繪制動作。drawImage方法將背景圖
48、放置在canvas的左上角(0,0)處。查看示例view pla inprint? fun ctio n draw() var ctx = docume nt.getEleme ntByld(ca nvas).getC on text(2d);var img = new Image();img. onl oad = function()ctx.drawlmage(img,O,O);ctx.begi nPath();ctx.moveTo(30,96);ctx.li neTo(70,66);ctx.li neTo(103,76);ctx.li neTo(170,15);ctx.stroke();i
49、mg.src = images/backdrop.p ng:縮放Scali ngdrawImage方法的又一變種是增加了兩個用于控制圖像在canvas中縮放的參數(shù)。drawImage(image, x, y, width, height)當(dāng)中width和height分別是圖像在canvas中顯示大小。drawImage示例2在這個例子里,我會用一張圖片像背景一樣在can vas中以重復(fù)平鋪開來。實現(xiàn)起來也很簡單,只需要循環(huán)鋪開經(jīng)過縮放的圖片即可。見下面的代碼,第一層for循環(huán)是做行重復(fù),第二層是做列重復(fù)的。圖像大小被縮放至原來的三分之一,50 x38 px。這種方法可以用來很好的達到背景圖案的
50、效果,在下面的教程中會看到。注意:圖像可能會因為大幅度的縮放而變得起雜點或者模糊。如果您的圖像里面有文字,那么 最好還是不要進行縮放,因為那樣處理之后很可能圖像里的文字就會變得無法辨認了。查看示例view pla inprint?fun ctio n draw() var ctx = docume nt.getEleme ntByld(ca nvas).getC on text(2d);var img = new Image();img. onl oad = function()for (i=0;i4;i+)for (j=0;j3;j+)ctx.drawlmage(img,j*50,i*38,
51、50,38);img.src = images/rh in o.jpg:切片SlicingdrawImage方法的第三個也是最后一個變種有8個新參數(shù),用于控制做切片顯示的。drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)第一個參數(shù)和其它的是相同的,都是一個圖像或者另一個canvas的引用。其它8個參數(shù)最好是參照右邊的圖解,前4個是定義圖像源的切片位置和大小,后4個則是定義切片的目標(biāo)顯示位置和大小。切片是個做圖像合成的強大工具。假設(shè)有一張包含了所有元素的圖像,那么你可以用這個方法來合成一個完整圖像。例如,你想畫一
52、張圖表,而手上有一個包含所有必需的文字的PNG文件,那么你可以很輕易的根據(jù)實際數(shù)據(jù)的需要來改變最終顯示的圖表。這方法的另一個好處就 是你不需要單獨裝載每一個圖像。drawImage示例3在這個例子里面我用到上面已經(jīng)用過的犀牛圖像,不過這次我要給犀牛頭做個切片特寫,然后 合成到一個相框里面去。相框帶有陰影效果,是一個以24-bit PNG格式保存的圖像。因為24-bit PNG圖像帶有一個完整的8-bit alpha通道,與GIF和8-bit PNG不同,我可以將它放成背景而不必擔(dān)心底色的問題。我用一個與上面用到的不同的方法來裝載圖像,直接將圖像插入到HTML里面,然后通過CSS隱藏(displ
53、ay:none)它。兩個圖像我都賦了id,方便后面使用??聪旅娴哪_本,相當(dāng)簡單,首先對犀牛頭做好切片(第一個drawImage )放在canvas上,然后再上面套個相框(第二個drawImage )。查看示例fun ctio n draw() var can vas = docume nt.getEleme ntByld(ca nvas);var ctx = can vas.getC on text(2d);/ Draw slicectx.drawlmage(docume nt.getEleme ntByld(source),33,71,104,124,21,20,87,104);/ Draw
54、 framectx.drawImage(docume nt.getEleme ntByld(frame),0,0);示例:畫廊Art gallery example我這一章最后的示例是弄一個小畫廊。畫廊由掛著幾張畫作的格子組成。當(dāng)頁面裝載好之后, 為每張畫創(chuàng)建一個canvas元素并用加上畫框然后插入到畫廊中去。在我這個例子里面,所有“畫”都是固定寬高的,畫框也是。你可以做些改進,通過腳本用畫 的寬高來準確控制圍繞它的畫框的大小。下面的代碼應(yīng)該是蠻自我解釋的了。就是遍歷圖像對象數(shù)組,依次創(chuàng)建新的canvas元素并添加進去。可能唯一需要注意的,對于那些并不熟悉DOM的朋友來說,是in sertBe
55、fore方法的用法。insertBefore是父節(jié)點(單元格)的方法,用于將新節(jié)點(canvas元素)插入到我們想要插入的節(jié)點之前。查看示例fun ctio n draw() / Loop through all imagesfor (i=0;idocume nt.images.le ngth;i+)/ Dont add a can vas for the frame imageif (docume nt.imagesi.getAttribute(id)!=frame)/ Create can vas eleme ntcan vas = docume nt.createEleme nt(CAN
56、VAS);can vas.setAttribute(width,132);can vas.setAttribute(height,150);/ Insert before the imagedocume nt.imagesi.pare ntNode.i nsertBefore(ca nvas,docume nt.imagesi);ctx = can vas.getC on text(2d);/ Draw image to can vasctx.drawImage(docume nt.imagesi,15,20);/ Add framectx.drawImage(docume nt.getEle
57、me ntByld(frame),0,0);控制圖像的縮放行為Co ntrolli ng image scali ng behaviorIn troduced in Gecko 1.9.2(Firefox 3.6 / Thu nderbird 3.1 / Fennec 1.0)Gecko 1.9.2引入了mozImageSmoothingEnabled屬性,值為false時,圖像不會平滑地縮放。默認是true。view pla inprint?cx.mozImageSmoothi ngEn abled = false;1.4應(yīng)用風(fēng)格和顏色運用樣式與顏色在繪制圖形 的章節(jié)里,我只用到默認的線條和
58、填充樣式。而在這一章里,我們將會探討canvas全部的可選項,來繪制出更加吸引人的內(nèi)容。色彩Colors到目前為止,我們只看到過繪制內(nèi)容的方法。如果我們想要給圖形上色,有兩個重要的屬性可以做到:fillStyle和strokeStyle。fillStyle = colorstrokeStyle = colorstrokeStyle是用于設(shè)置圖形輪廓的顏色,而fillStyle用于設(shè)置填充顏色。color可以是表示CSS顏色值的字符串,漸變對象或者圖案對象。我們遲些再回頭探討漸變和圖案對象。默認情況下,線條和填充顏色都是黑色(CSS顏色值#000000)。您輸入的應(yīng)該是符合CSS3顏色值標(biāo)準的有
59、效字符串。下面的例子都表示同一種顏色。/這些fillStyle的值均為橙色ctx.fillStyle = ora nge;ctx.fillStyle = #FFA500;ctx.fillStyle = rgb(255,165,0);ctx.fillStyle = rgba(255,165,0,1);注意:目前Gecko引擎并沒有提供對所有的CSS 3顏色值的支持。例如,hsl(100%,25%,0)或者rgb(0,100%,0)都不可用。但如果您遵循上面例子的規(guī)范,應(yīng)該不會有問題。注意:一旦您設(shè)置了strokeStyle或者fillStyle的值,那么這個新值就會成為新繪制的圖 形的默認值。如
60、果你要給每個圖形上不同的顏色,你需要重新設(shè)置fillStyle或strokeStyle的值。fillStyle示例在本示例里,我會再度用兩層for循環(huán)來繪制方格陣列,每個方格不同的顏色。結(jié)果如右圖,但實現(xiàn)所用的代碼卻沒那么絢麗。我用了兩個變量i和j來為每一個方格產(chǎn)生唯一的RGB色彩值,其中僅修改紅色和綠色通道的值,而保持藍色通道的值不變。你可以通過修改這 些顏色通道的值來產(chǎn)生各種各樣的色板。通過增加漸變的頻率,你還可以繪制出類似Photoshop里面的那樣的調(diào)色板。查看示例fun ctio n draw() var ctx = docume nt.getEleme ntByld(ca nvas
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五年購銷合同:某鋼鐵企業(yè)向供應(yīng)商訂購0萬噸原材料2篇
- 二零二五年度高鐵站房PC構(gòu)件預(yù)制及吊裝工程合同2篇
- 二零二五年度物業(yè)管理顧問合同(含交通樞紐管理)2篇
- 二零二五版貨車司機意外傷害賠償合同范本3篇
- 二零二五年度綠色環(huán)保型二手房按揭交易合同模板3篇
- 二零二五食堂承包合同(大路食堂運營管理)3篇
- 二零二五版二手房買賣與家具選購代理合同3篇
- 稅務(wù)局2025年度企業(yè)社會責(zé)任報告編制合同
- 二零二五年度智慧社區(qū)家居安裝合同規(guī)范3篇
- 二零二五年度蟲草科研合作與技術(shù)轉(zhuǎn)移合同范本3篇
- 社會學(xué)概論課件
- 華為經(jīng)營管理-華為的研發(fā)管理(6版)
- C及C++程序設(shè)計課件
- 帶狀皰疹護理查房
- 公路路基路面現(xiàn)場測試隨機選點記錄
- 平衡計分卡-化戰(zhàn)略為行動
- 國家自然科學(xué)基金(NSFC)申請書樣本
- 湖南省省級溫室氣體排放清單土地利用變化和林業(yè)部分
- 材料設(shè)備驗收管理流程圖
- 培訓(xùn)機構(gòu)消防安全承諾書范文(通用5篇)
- (完整版)建筑業(yè)10項新技術(shù)(2017年最新版)
評論
0/150
提交評論