<canvas></canvas>
是HTML5中新增的標籤,用於繪製圖形,實際上,這個標籤和其他的標籤一樣,其特殊之處在於該標籤可以獲取一個CanvasRenderingContext2D對象,我們可以透過JavaScript腳本來控制該物件進行繪圖。
<canvas></canvas>
只是一個繪製圖形的容器,除了id、class、style等屬性外,還有height和width屬性。在<canvas>>
元素上繪圖主要有三步驟:
<canvas>
元素對應的DOM對象,這是一個Canvas物件;以下是一個簡單的<canvas>
繪圖範例:
<!DOCTYPE html><html lang=en><head> <meta charset=UTF-8> <title>canvas繪圖示範</title> <style type=text/css> #canvas{ border: 1px solid #ADACB0; display: block; margin: 20px auto; } </style></head><body> <canvas id=canvas width=300 height=300> 你的瀏覽器還不支援canvas </canvas></body><script type=text/javascript> var canvas = document.getElementById(canvas); var context = canvas.getContext(2d); //設定物件起始點和終點context.moveTo(10,10); context.lineTo(200,200); //設定樣式context.lineWidth = 2; context.strokeStyle = #F5270B; //繪製context.stroke();</script></html>
如果沒有透過moveTo()特別指定,lineTo()的起始點是以上一個點為準。因此,如果需要重新選擇起始點,則需要透過moveTo()方法。如果需要對不同的線段設定樣式,則需要透過context.beginPath()重新開啟一條路徑,下面是一個範例:
<script type=text/javascript> var canvas = document.getElementById(canvas); var context = canvas.getContext(2d); //設定物件起始點和終點context.beginPath(); context.moveTo(100,100); context .lineTo(700,100); context.lineTo(700,400); context.lineWidth = 2; context.strokeStyle = #F5270B; //繪製context.stroke(); context.beginPath(); context.moveTo(100,200);//這裡的moveTo換成lineTo效果是一樣的context.lineTo(600,200) ; context.lineTo(600,400); //strokeStyle的顏色有新的值,則覆蓋上面設定的值//lineWidth沒有新的值,則按上面設定的值顯示context.strokeStyle = #0D25F6; //繪製context.stroke();</script >
繪製矩形rect()、fillRect()和strokeRect()
<script type=text/javascript> var canvas = document.getElementById(canvas); var context = canvas.getContext(2d); //使用rect方法context.rect(10,10,190,190); context.lineWidth = 2; context. fillStyle = #3EE4CB; context.strokeStyle = #F5270B; context.fill(); context.stroke(); //使用fillRect方法context.fillStyle = #1424DE; context.fillRect(210,10,190,190); //使用strokeRect方法context.strokeStyle = #F5270Bect contextke ,10,190,190); //同時使用strokeRect方法和fillRect方法context.fillStyle = #1424DE; context.strokeStyle = #F5270B; context.strokeRect(610,10,190,190); context.fillRect(610,10,190,190);
這裡需要說明兩點:第一點就是stroke()和fill()繪製的前後順序,如果fill()後面繪製,那麼當stroke邊框較大時,會明顯的把stroke()繪製出的邊框遮住一半;第二點:設定fillStyle或strokeStyle屬性時,可以透過rgba(255,0,0,0.2)的設定方式來設置,這個設定的最後一個參數是透明度。
另外還有一個跟矩形繪製有關的:清除矩形區域:context.clearRect(x,y,width,height)。
接收參數分別為:清除矩形的起始位置以及矩形的寬度和長度。
在上面的程式碼中繪製圖形的最後加上:
context.clearRect(100,60,600,100);
可以得到以下效果:
繪製五角星透過對五角星分析,我們可以確定各個頂點座標的規律,這裡需要注意的一點是:在canvas中,Y軸的方向是向下的。
對應程式碼如下:
var canvas = document.getElementById(canvas); var context = canvas.getContext(2d); context.beginPath(); //設定是個頂點的座標,根據頂點制定路徑for (var i = 0; i < 5; i++ ) { context.lineTo(Math.cos((18+i*72)/180*Math.PI)*200+200, -Math.sin((18+i*72)/180*Math.PI)*200+200); context.lineTo(Math.cos((54+i*72)/180*Math.PI)*80+ 200, -Math.sin((54+i*72)/180*Math.PI)*80+200); } context.closePath(); //設定邊框樣式以及填滿顏色context.lineWidth=3; context.fillStyle = #F6F152; context.strokeStyle = #F5270B; context.fill(); context.stroke();
最後效果:
線條屬性除了上面用到的lineWidth屬性,線條還有以下幾個屬性:
lineCap 屬性設定或傳回線條末端線帽的樣式,可以取以下幾個值:
lineJoin 屬性當兩條線交會時設定或傳回所建立邊角的類型,可以取以下幾個值:
miterLimit 屬性設定或傳回最大斜接長度(預設為10)。斜接長度指的是兩條線交會處內角和外角之間的距離。只有當lineJoin 屬性為miter 時,miterLimit 才會有效。
var canvas = document.getElementById(canvas); var context = canvas.getContext(2d); //測試lineCap屬性//設定基準線便於觀察context.moveTo(10,10); context.lineTo(10,200); context. moveTo(200,10); context.lineTo(200,200); context.lineWidth=1; context.stroke(); //butt context.beginPath(); context.moveTo(10,50); context.lineTo(200,50); context.lineCap=butt; context.lineWidth=10 ; context.stroke(); //round context.beginPath(); context.moveTo(10,100); context.lineTo(200,100); context.lineCap=round; context.lineWidth=10; context.stroke(); //square context.beginPath(); context.moveTo(10,150); context.lineTo(200,150); context. lineCap=square; context.lineWidth=10; context.stroke(); //測試linJoin屬性//miter context.beginPath(); context.moveTo(300,50); context.lineTo(450,100); context.lineTo(300,150); context.lineJoin=miter; context.lineWidth=10; context .stroke(); //round context.beginPath(); context.moveTo(400,50); context.lineTo(550,100); context.lineTo(400,150); context.lineJoin=round; context.lineWidth=10; context.stroke(); //square context.beginPath(); context.moveTo(500,50); context.lineTo(650,100); context.lineTo(500,150); context.lineJoin=bevel; context.lineWidth=10; context.stroke(); //測試miterLimit屬性context.beginPath(); context.moveTo(700,50); context.lineTo(850,100 ); context.lineTo(700,150); context.lineJoin=miter; context.miterLimit=2; context.lineWidth=10; context.strokeStyle=#2913EC; context.stroke();
各屬性的不同取值的效果如下:
填滿樣式前面用到的fillStyle和strokeStyle除了設定顏色外,還能設定其他填滿樣式,這裡以fillStyle為例:
線性漸變使用步驟
(1)var grd = context.createLinearGradient( xstart , ystart, xend , yend )建立一個線性漸變,設定起始座標和終點座標;
(2)grd.addColorStop( stop , color )為線性漸變加色,stop為0~1的值;
(3)context.fillStyle=grd將賦值給context。
徑向漸變此方法與線性漸變使用方法類似,只是第一步接收的參數不一樣
var grd = context.createRadialGradient(x0 , y0, r0 , x1 , y1 , r1 );接收起始圓心的座標和圓半徑以及終點圓心的座標和圓的半徑。
點陣圖填充createPattern( img , repeat-style )使用圖片填充,repeat-style可以取repeat、repeat-x、repeat-y、no-repeat。
var canvas = document.getElementById(canvas); var context = canvas.getContext(2d); //線性漸變var grd = context.createLinearGradient( 10 , 10, 100 , 350 ); grd.addd. grd.addColorStop(0.25,#FC0F31); grd.addColorStop(0.5,#ECF811); grd.addColorStop(0.75,#2F0AF1); grd.addColorStop(1,#160303); contextF0AF1); grd.addColorStop(1,#160303); context.fillStyle = grectill; 10,10,100,350); //徑向漸層var grd = context.createRadialGradient(325 , 200, 0 , 325 , 200 , 200 ); grd.addColorStop(0,#1EF9F7); grd.addColoradd0.25,#FC0F31); ,#ECF811); grd.addColorStop(0.75,#2F0AF1); grd.addColorStop(1,#160303); context.fillStyle = grd; context.fillRect(150,10,350,350); //位元圖填入 bgimgmg = newk Image(); src = background.jpg; bgimg.onload=function(){ var pattern = context.createPattern(bgimg, repeat); context.fillStyle = pattern; context.strokeStyle=#F20B0B; context.fillRect(600, 100, 200,200B; context.fillRect(600, 100, 200,2000); 100, 200,200); };
效果如下:
圖形變換平移:context.translate(x,y),接收參數分別為原點在x軸方向平移x,在y軸方向平移y。
縮放:context.scale(x,y),接收參數分別為x座標軸以x比例縮放,y座標軸以y比例縮放。
旋轉:context.rotate(angle),接收參數是座標軸旋轉的角度。
需要說明的是,對圖形進行變更後,接下來的一次繪圖是緊接著上一次的狀態的,所以如果需要回到初始狀態,要用到context.save();
和context.restore();
來儲存和恢復目前狀態:
var canvas = document.getElementById(canvas); var context = canvas.getContext(2d); //translate() context.save(); context.fillStyle = #1424DE; context.translate(10,10); context.fillRect (0,0,200,200); context.restore(); //scale() context.save(); context.fillStyle = #F5270B; context.scale(0.5,0.5); context.fillRect(500,50,200,200); context.restore(); //rotate() context.save(); context. fillStyle = #18EB0F; context.rotate(Math.PI / 4); context.fillRect(300,10,200,200); context.restore();
效果如下:
另外一個跟圖形變換相關的是:矩陣變換:context.transform(a, b, c, d, e, f, g)。參數的意思如下:
a 水平縮放( 預設為1 )
b 水平傾斜( 預設為0 )
c 垂直傾斜( 預設為0 )
d 垂直縮放( 預設為1 )
e 水平位移( 預設為0 )
f 垂直位移( 預設為0 )
讀者可以自行驗證其各個參數的效果,這裡就不一一介紹了。
繪製曲線跟繪製曲線的有四個函數,分別是:
context.arc(x,y,r,sAngle,eAngle,counterclockwise);用於建立弧/曲線(用於建立圓或部分圓)。接收的參數意義:
| 參數| 意義|
| :--- |:---|
| x | 圓的中心的x 座標|
|y|圓的中心的y 座標|
|r|圓的半徑|
|sAngle|起始角,以弧度計(弧的圓形的三點鐘位置是0 度)|
|eAngle|結束角,以弧度計|
|counterclockwise|可選。規定應該逆時針還是順時針繪圖。 False = 順時針,true = 逆時針|
下面是幾個arc()函數的幾個範例:
var canvas = document.getElementById(canvas); var context = canvas.getContext(2d); context.strokeStyle = #F22D0D; context.lineWidth = 2; //繪製圓context.beginPath(); context.arc(100,100,440,100,444 ,0,2*Math.PI); context.stroke(); //繪製半圓context.beginPath(); context.arc(200,100,40,0,Math.PI); context.stroke(); //繪製半圓,逆時針context.beginPath(); context.arc(300,100, 40,0,Math.PI,true); context.stroke(); //繪製封閉半圓context.beginPath(); context.arc(400,100,40,0,Math.PI); context.closePath(); context.stroke();
效果如下:
context.arcTo(x1,y1,x2,y2,r); 在畫布上建立介於兩條切線之間的弧/曲線。接收的參數意義:
參數 | 意義 |
---|---|
x1 | 弧的控制點的x 座標 |
y1 | 弧的控制點的y 座標 |
x2 | 弧的終點的x 座標 |
y2 | 弧的終點的y 座標 |
r | 弧的半徑 |
這裡要注意的是arcTo函數繪製的曲線的起始點需要透過moveTo()函數來設置,下面利用arcTo函數繪製一個圓角矩形:
function createRoundRect(context , x1 , y1 , width , height , radius) { // 移到左上角context.moveTo(x1 + radius , y1); // 加一條連接到右上角的線段context.lineTox1 + width - radius, y1); // 加一段圓弧context.arcTo(x1 + width , y1, x1 + width, y1 + radius, radius); // 加一條連接到右下角的線段context.lineTo(x1 + width, y1 + height - radius); // 加一段圓弧context.arcTo(x1 + width, y1 + height , x1 + width - radius, y1 + height , radius); //加一條連接到左下角的線段context.lineTo(x1 + radius, y1 + height); // 加一段圓弧context.arcTo(x1, y1 + height , x1 , y1 + height - radius , radius); //新增一條連接到左上角的線段context.lineTo(x1 , y1 + radius); //加入一段圓弧context.arcTo(x1 , y1 , x1 + radius , y1 , radius); context.closePath(); } // 取得canvas元素對應的DOM物件var canvas = document.getElementById('mc'); / / 取得在canvas上繪圖的CanvasRenderingContext2D物件var context = canvas.getContext('2d'); context.lineWidth = 3; context.strokeStyle = #F9230B; createRoundRect(context , 30 , 30 , 400 , 200 , 50); context.stroke();
效果如下:
context.quadraticCurveTo(cpx,cpy,x,y);繪製二次貝塞曲線,參數意義如下:
參數 | 意義 |
---|---|
cpx | 貝塞爾控制點的x 座標 |
cpy | 貝塞爾控制點的y 座標 |
x | 結束點的x 座標 |
y | 結束點的y 座標 |
曲線的開始點是目前路徑中最後一個點。如果路徑不存在,那麼請使用beginPath() 和moveTo() 方法來定義起點。
context.bezierCurveTo(cp1x,cp1y,cp2x,cp2y,x,y); 繪製三次貝塞爾曲線,參數如下:
參數 | 意義 |
---|---|
cp1x | 第一個貝塞爾控制點的x 座標 |
cp1y | 第一個貝塞爾控制點的y 座標 |
cp2x | 第二個貝塞爾控制點的x 座標 |
cp2y | 第二個貝塞爾控制點的y 座標 |
x | 結束點的x 座標 |
y | 結束點的y 座標 |
與文字渲染有關的主要有三個屬性以及三個方法:
屬性 | 描述 |
---|---|
font | 設定或傳回文字內容的目前字體屬性 |
textAlign | 設定或傳回文字內容的目前對齊方式 |
textBaseline | 設定或返回在繪製文字時使用的目前文字基線 |
方法 | 描述 |
---|---|
fillText() | 在畫布上繪製被填充的文本 |
strokeText() | 在畫布上繪製文字(無填充) |
measureText() | 傳回包含指定文字寬度的對象 |
上述的屬性和方法的基本用法如下:
var canvas = document.getElementById(canvas); var context = canvas.getContext(2d); context.font=bold 30px Arial; //設定樣式context.strokeStyle = #1712F4; context.strokeText(歡迎來到我的部落格! ,30,100); context.font=bold 50px Arial; var grd = context.createLinearGradient( 30 , 200, 400 , 300 );//設定漸變填滿樣式grd.addColorStop(0,#1EF9F7); grd.addColorStop(0.25,#FC0F31); grd.addor#0. grd.addColorStop(0.75,#2F0AF1); grd.addColorStop(1,#160303); context.fillStyle = grd; context.fillText(歡迎來到我的部落格!,30,200); context.save(); context.moveTo); (200,280); context.lineTo(200,420); context.stroke(); context.font=bold 20px Arial; context.fillStyle = #F80707; context.textAlign=left; context.fillText(文字在指定的位置開始,200,300); context.textAlign=center; context.fillText=center; context.fillText=center; context.fillText=center; context.fillText=center; context.fillText=center; context.fillText=center; context.fillText=center; context.fillText. (文本的中心被放置在指定的位置,200,350); context.textAlign=right; context.fillText(文字在指定的位置結束,200,400); context.restore(); context.save(); context.moveTo(10,500); context.lineTo(500,500); context.stroke(); context.fillStylineTo(500,500); context.stroke(); context.fillStylineTo(500,500); context.stroke(); context.fillStyle= #F60D0D; context.font=bold 20px Arial; context.textBaseline=top; context.fillText(指定位置在上方,10,500); context.textBaseline=bottom; context.fillText(指定位置在下方,150,500); context.textBaseline=middle; context.fillText(指定位置居中,300,500); context.restore (); context.font=bold 40px Arial; context.strokeStyle = #16F643; var text = 歡迎來到我的部落格! ; context.strokeText(歡迎來到我的部落格!,10,600); context.strokeText(上面字串的寬度為:+context.measureText(text).width,10,650);
效果如下:
其他屬性和方法陰影繪製:我們為之前繪製的五角星添加一下陰影
var canvas = document.getElementById(canvas); var context = canvas.getContext(2d); context.beginPath(); //設定是個頂點的座標,根據頂點制定路徑for (var i = 0; i < 5; i++ ) { context.lineTo(Math.cos((18+i*72)/180*Math.PI)*200+200, -Math.sin((18+i*72)/180*Math.PI)*200+200); context.lineTo(Math.cos((54+i*72)/180*Math.PI)*80+ 200, -Math.sin((54+i*72)/180*Math.PI)*80+200); } context.closePath(); //設定邊框樣式以及填滿顏色context.lineWidth=3; context.fillStyle = #F6F152; context.strokeStyle = #F5270B; context.shadowColor = #F7F2B4; context.shadowOffsetX = 30; context = 2; context.fill(); context.stroke();
效果如下:
圖形組合:globalAlpha: 設定或傳回繪圖的目前alpha 或透明值
方法主要是設定圖形的透明度,這裡就不具體介紹。
globalCompositeOperation: 設定或傳回新影像如何繪製到現有的影像上,此方法有以下屬性值:
值 | 描述 |
---|---|
source-over | 在目標影像上顯示來源影像(預設) |
source-atop | 在目標影像頂部顯示來源影像。來源影像位於目標影像之外的部分是不可見的 |
source-in | 在目標影像中顯示來源影像。只有目標影像之內的來源影像部分會顯示,目標影像是透明的 |
source-out | 在目標影像之外顯示來源影像。只有目標影像以外的來源影像部分會顯示,目標影像是透明的 |
destination-over | 在來源影像上顯示目標影像 |
destination-atop | 在來源影像頂部顯示目標影像。目標影像位於來源影像之外的部分是不可見的 |
destination-in | 在來源影像中顯示目標影像。只有在來源影像之內的目標影像部分會被顯示,而來源影像是透明的 |
destination-out | 在來源影像之外顯示目標影像。只有來源影像以外的目標影像部分會被顯示,來源影像是透明的 |
lighter | 顯示來源影像+ 目標影像 |
copy | 顯示來源影像。忽略目標影像 |
xor | 使用異或操作對來源影像與目標影像進行組合 |
下面是一個小範例,可以透過點擊來改變組合效果:
<!DOCTYPE html><html lang=en><head> <meta charset=UTF-8> <title>圖形組合</title> <style type=text/css> #canvas{ border: 1px solid #1C0EFA; display : block; margin: 20px auto; } #buttons{ width: 1000px; margin: 5px auto; clear:both; } #buttons a{ font-size: 18px; display: block; float: left; margin-left: 20px; } </style></head><body> <canvas id=canvas width= 1000 height=800> 你的瀏覽器還不支援canvas </canvas> <div id=buttons> <a href=#>source-over</a> <a href=#>source-atop</a> <a href=#>source-in</a> <a href=#>source-out</a> <a href=#>destination-over</a> <a href=#>destination-atop</a> <a href=#>destination-in</a> <a href=#>destination-out</ a> <a href=#>lighter</a> <a href=#>copy</a> <a href=#>xor</a> </div></body><script type=text/javascript>window.onload = function(){ draw(source-over) ; var buttons = document.getElementById(buttons).getElementsByTagName(a); for (var i = 0; i < buttons.length; i++) { buttons[i].onclick = function(){ draw(this.text); return false; }; }}; function draw(compositeStyle){ var canvas = document.getElementById(canvas); var context = canvas.getContext(2d ); context.clearRect(0, 0, canvas.width, canvas.height); //draw title context.font = bold 40px Arial; context.textAlign = center; context.textBasedline = middle; context.fillStyle = #150E0E; context.fillText(globalCompositeOperation = +compositeStyle, canvas.60th/2, width /draw a rect context.fillStyle = #F6082A; context.fillRect(300, 150, 500, 500); //draw a triangle context.globalCompositeOperation = compositeStyle; context.fillStyle = #1611F5; context.bemPath(); context.500); context.lineTo(1000,750); context.lineTo(400, 750); context.closePath(); context.fill(); }</script></html>
讀者可以點選標籤觀察不同的組合效果,效果如下:
剪輯區域:clip()方法從原始畫布中剪下任意形狀和尺寸。
提示:一旦剪切了某個區域,則所有之後的繪圖都會被限制在被剪切的區域內(不能訪問畫布上的其他區域)。您也可以在使用clip() 方法前透過使用save() 方法對目前畫布區域進行儲存,並在以後的任何時間進行還原(透過restore() 方法)
以下是用一個圓去截取一個矩形的範例:
var canvas = document.getElementById(canvas); var context = canvas.getContext(2d); context.beginPath(); context.fillStyle = #0C0101; context.fillRect(0,0,canvas.width,canvas.height); context.beginPath(); context.fillStyle = #FFFDFD; context.arc(400,400,100,0,2*Math.PI); context.fill(); context.clip(); context.beginPath(); context.fillStyle = #F60825; context.fillRect(200, 350, 400, 50);
除了上述的屬性的和方法,還有以下等方法:
drawImage(): 向畫布上繪製影像、畫布或影片。
toDataURL() :儲存圖形
isPointInPath(): 如果指定的點位於目前路徑中,則傳回true,否則傳回false。
這裡就不逐一舉例說明了。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VeVb武林網。