什么是HTML5 canvas繪圖?相信很多沒有經(jīng)驗的人對此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個問題。
公司主營業(yè)務(wù):成都網(wǎng)站建設(shè)、成都網(wǎng)站制作、移動網(wǎng)站開發(fā)等業(yè)務(wù)。幫助企業(yè)客戶真正實現(xiàn)互聯(lián)網(wǎng)宣傳,提高企業(yè)的競爭能力。創(chuàng)新互聯(lián)建站是一支青春激揚、勤奮敬業(yè)、活力青春激揚、勤奮敬業(yè)、活力澎湃、和諧高效的團(tuán)隊。公司秉承以“開放、自由、嚴(yán)謹(jǐn)、自律”為核心的企業(yè)文化,感謝他們對我們的高要求,感謝他們從不同領(lǐng)域給我們帶來的挑戰(zhàn),讓我們激情的團(tuán)隊有機(jī)會用頭腦與智慧不斷的給客戶帶來驚喜。創(chuàng)新互聯(lián)建站推出思禮免費做網(wǎng)站回饋大家。
是HTML5中新增的標(biāo)簽,用于繪制圖形,實際上,這個標(biāo)簽和其他的標(biāo)簽一樣,其特殊之處在于該標(biāo)簽可以獲取一個CanvasRenderingContext2D對象,我們可以通過JavaScript腳本來控制該對象進(jìn)行繪圖。
只是一個繪制圖形的容器,除了id、class、style等屬性外,還有height和width屬性。在
元素上繪圖主要有三步:
獲取元素對應(yīng)的DOM對象,這是一個Canvas對象;
調(diào)用Canvas對象的getContext()方法,得到一個CanvasRenderingContext2D對象;
調(diào)用CanvasRenderingContext2D對象進(jìn)行繪圖。
繪制線段moveTo()和lineTo()
以下是一個簡單的繪圖示例:
canvas繪圖演示
如果沒有通過moveTo()特別指定,lineTo()的起始點是以上一個點為準(zhǔn)。因此,如果需要重新選擇起始點,則需要通過moveTo()方法。如果需要對不同的線段設(shè)置樣式,則需要通過context.beginPath()重新開啟一條路徑,下面是一個示例:
繪制矩形rect()、fillRect()和strokeRect()
context.rect( x , y , width , height ):只定義矩形的路徑;
context.fillRect( x , y , width , height ):直接繪制出填充的矩形;
context.strokeRect( x , y , width , height ):直接繪制出矩形邊框;
這里需要說明兩點:第一點就是stroke()和fill()繪制的前后順序,如果fill()后面繪制,那么當(dāng)stroke邊框較大時,會明顯的把stroke()繪制出的邊框遮住一半;第二點:設(shè)置fillStyle或strokeStyle屬性時,可以通過“rgba(255,0,0,0.2)”的設(shè)置方式來設(shè)置,這個設(shè)置的最后一個參數(shù)是透明度。
另外還有一個跟矩形繪制有關(guān)的:清除矩形區(qū)域:context.clearRect(x,y,width,height)。
接收參數(shù)分別為:清除矩形的起始位置以及矩形的寬和長。
在上面的代碼中繪制圖形的最后加上:
context.clearRect(100,60,600,100);
可以得到以下效果:
繪制五角星
通過對五角星分析,我們可以確定各個頂點坐標(biāo)的規(guī)律,這里需要注意的一點是:在canvas中,Y軸的方向是向下的。
相應(yīng)代碼如下:
var canvas = document.getElementById("canvas"); var context = canvas.getContext("2d"); context.beginPath(); //設(shè)置是個頂點的坐標(biāo),根據(jù)頂點制定路徑 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(); //設(shè)置邊框樣式以及填充顏色 context.lineWidth="3"; context.fillStyle = "#F6F152"; context.strokeStyle = "#F5270B"; context.fill(); context.stroke();
最后效果:
線條屬性
除了上面用到的lineWidth屬性,線條還有以下幾個屬性:
lineCap 屬性設(shè)置或返回線條末端線帽的樣式,可以取以下幾個值:
“butt” 向線條的每個末端添加平直的邊緣(默認(rèn));
“round” 向線條的每個末端添加圓形線帽;
“square” 向線條的每個末端添加正方形線帽。
lineJoin 屬性當(dāng)兩條線交匯時設(shè)置或返回所創(chuàng)建邊角的類型,可以取以下幾個值:
“miter” 創(chuàng)建尖角(默認(rèn));
“bevel” 創(chuàng)建斜角;
“round” 創(chuàng)建圓角。
miterLimit 屬性設(shè)置或返回最大斜接長度(默認(rèn)為10)。斜接長度指的是在兩條線交匯處內(nèi)角和外角之間的距離。只有當(dāng) lineJoin 屬性為 “miter” 時,miterLimit 才有效。
var canvas = document.getElementById("canvas"); var context = canvas.getContext("2d"); //測試lineCap屬性 //設(shè)置基準(zhǔn)線便于觀察 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除了設(shè)置顏色外,還能設(shè)置其他填充樣式,這里以fillStyle為例:
線性漸變
使用步驟
(1)var grd = context.createLinearGradient( xstart , ystart, xend , yend )創(chuàng)建一個線性漸變,設(shè)置起始坐標(biāo)和終點坐標(biāo);
(2)grd.addColorStop( stop , color )為線性漸變添加顏色,stop為0~1的值;
(3)context.fillStyle=grd將賦值給context。
徑向漸變
該方法與線性漸變使用方法類似,只是第一步接收的參數(shù)不一樣
var grd = context.createRadialGradient(x0 , y0, r0 , x1 , y1 , r1 );接收起始圓心的坐標(biāo)和圓半徑以及終點圓心的坐標(biāo)和圓的半徑。
位圖填充
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.addColorStop(0,"#1EF9F7"); grd.addColorStop(0.25,"#FC0F31"); grd.addColorStop(0.5,"#ECF811"); grd.addColorStop(0.75,"#2F0AF1"); grd.addColorStop(1,"#160303"); context.fillStyle = grd; context.fillRect(10,10,100,350); //徑向漸變 var grd = context.createRadialGradient(325 , 200, 0 , 325 , 200 , 200 ); grd.addColorStop(0,"#1EF9F7"); grd.addColorStop(0.25,"#FC0F31"); grd.addColorStop(0.5,"#ECF811"); grd.addColorStop(0.75,"#2F0AF1"); grd.addColorStop(1,"#160303"); context.fillStyle = grd; context.fillRect(150,10,350,350); //位圖填充 var bgimg = new Image(); bgimg.src = "background.jpg"; bgimg.onload=function(){ var pattern = context.createPattern(bgimg, "repeat"); context.fillStyle = pattern; context.strokeStyle="#F20B0B"; context.fillRect(600, 100, 200,200); context.strokeRect(600, 100, 200,200); };
效果如下:
圖形變換
平移:context.translate(x,y),接收參數(shù)分別為原點在x軸方向平移x,在y軸方向平移y。
縮放:context.scale(x,y),接收參數(shù)分別為x坐標(biāo)軸按x比例縮放,y坐標(biāo)軸按y比例縮放。
旋轉(zhuǎn):context.rotate(angle),接收參數(shù)是坐標(biāo)軸旋轉(zhuǎn)的角度。
需要說明的是,對圖形進(jìn)行變化后,接下來的一次繪圖是緊接著上一次的狀態(tài)的,所以如果需要回到初始狀態(tài),要用到context.save();
和context.restore();
來保存和恢復(fù)當(dāng)前狀態(tài):
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();
效果如下:
另外一個跟圖形變換相關(guān)的是:矩陣變換 :context.transform(a, b, c, d, e, f, g)。參數(shù)的含義如下:
a 水平縮放 ( 默認(rèn)為1 )
b 水平傾斜 ( 默認(rèn)為 0 )
c 垂直傾斜 ( 默認(rèn)為 0 )
d 垂直縮放 ( 默認(rèn)為1 )
e 水平位移 ( 默認(rèn)為 0 )
f 垂直位移 ( 默認(rèn)為 0 )
讀者可以自行驗證其各個參數(shù)的效果,這里就不一一介紹了。
繪制曲線
跟繪制曲線的有四個函數(shù),分別是:
context.arc(x,y,r,sAngle,eAngle,counterclockwise);用于創(chuàng)建弧/曲線(用于創(chuàng)建圓或部分圓)。接收的參數(shù)含義:
| 參數(shù) | 含義 |
| :————- |:————-|
| x | 圓的中心的 x 坐標(biāo) |
|y|圓的中心的 y 坐標(biāo)|
|r|圓的半徑|
|sAngle|起始角,以弧度計(弧的圓形的三點鐘位置是 0 度)|
|eAngle|結(jié)束角,以弧度計|
|counterclockwise|可選。規(guī)定應(yīng)該逆時針還是順時針繪圖。False = 順時針,true = 逆時針|
下面是幾個arc()函數(shù)的幾個示例:
var canvas = document.getElementById("canvas"); var context = canvas.getContext("2d"); context.strokeStyle = "#F22D0D"; context.lineWidth = "2"; //繪制圓 context.beginPath(); context.arc(100,100,40,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); 在畫布上創(chuàng)建介于兩個切線之間的弧/曲線。接收的參數(shù)含義:
參數(shù) | 含義 |
---|---|
x1 | 弧的控制點的 x 坐標(biāo) |
y1 | 弧的控制點的 y 坐標(biāo) |
x2 | 弧的終點的 x 坐標(biāo) |
y2 | 弧的終點的 y 坐標(biāo) |
r | 弧的半徑 |
這里需要注意的是arcTo函數(shù)繪制的曲線的起始點需要通過moveTo()函數(shù)來設(shè)置,下面利用arcTo函數(shù)繪制一個圓角矩形:
function createRoundRect(context , x1 , y1 , width , height , radius) { // 移動到左上角 context.moveTo(x1 + radius , y1); // 添加一條連接到右上角的線段 context.lineTo(x1 + 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元素對應(yīng)的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);繪制二次貝塞曲線,參數(shù)含義如下:
參數(shù) | 含義 |
---|---|
cpx | 貝塞爾控制點的 x 坐標(biāo) |
cpy | 貝塞爾控制點的 y 坐標(biāo) |
x | 結(jié)束點的 x 坐標(biāo) |
y | 結(jié)束點的 y 坐標(biāo) |
曲線的開始點是當(dāng)前路徑中最后一個點。如果路徑不存在,那么請使用 beginPath() 和 moveTo() 方法來定義開始點。
context.bezierCurveTo(cp1x,cp1y,cp2x,cp2y,x,y); 繪制三次貝塞爾曲線,參數(shù)如下:
參數(shù) | 含義 |
---|---|
cp1x | 第一個貝塞爾控制點的 x 坐標(biāo) |
cp1y | 第一個貝塞爾控制點的 y 坐標(biāo) |
cp2x | 第二個貝塞爾控制點的 x 坐標(biāo) |
cp2y | 第二個貝塞爾控制點的 y 坐標(biāo) |
x | 結(jié)束點的 x 坐標(biāo) |
y | 結(jié)束點的 y 坐標(biāo) |
文字渲染
與文本渲染有關(guān)的主要有三個屬性以及三個方法:
屬性 | 描述 |
---|---|
font | 設(shè)置或返回文本內(nèi)容的當(dāng)前字體屬性 |
textAlign | 設(shè)置或返回文本內(nèi)容的當(dāng)前對齊方式 |
textBaseline | 設(shè)置或返回在繪制文本時使用的當(dāng)前文本基線 |
方法 | 描述 |
---|---|
fillText() | 在畫布上繪制”被填充的”文本 |
strokeText() | 在畫布上繪制文本(無填充) |
measureText() | 返回包含指定文本寬度的對象 |
上述的屬性和方法的基本用法如下:
var canvas = document.getElementById("canvas"); var context = canvas.getContext("2d"); context.font="bold 30px Arial"; //設(shè)置樣式 context.strokeStyle = "#1712F4"; context.strokeText("歡迎來到我的博客!",30,100); context.font="bold 50px Arial"; var grd = context.createLinearGradient( 30 , 200, 400 , 300 );//設(shè)置漸變填充樣式 grd.addColorStop(0,"#1EF9F7"); grd.addColorStop(0.25,"#FC0F31"); grd.addColorStop(0.5,"#ECF811"); 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("文本的中心被放置在指定的位置",200,350); context.textAlign="right"; context.fillText("文本在指定的位置結(jié)束",200,400); context.restore(); context.save(); context.moveTo(10,500); context.lineTo(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);
效果如下:
其他屬性和方法
陰影繪制:
shadowColor 設(shè)置或返回用于陰影的顏色。
shadowBlur 設(shè)置或返回用于陰影的模糊級別(數(shù)值越大越模糊)。
shadowOffsetX 設(shè)置或返回陰影與形狀的水平距離。
shadowOffsetY 設(shè)置或返回陰影與形狀的垂直距離。
我們?yōu)橹袄L制的五角星添加一下陰影
var canvas = document.getElementById("canvas"); var context = canvas.getContext("2d"); context.beginPath(); //設(shè)置是個頂點的坐標(biāo),根據(jù)頂點制定路徑 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(); //設(shè)置邊框樣式以及填充顏色 context.lineWidth="3"; context.fillStyle = "#F6F152"; context.strokeStyle = "#F5270B"; context.shadowColor = "#F7F2B4"; context.shadowOffsetX = 30; context.shadowOffsetY = 30; context.shadowBlur = 2; context.fill(); context.stroke();
效果如下:
圖形組合:
globalAlpha: 設(shè)置或返回繪圖的當(dāng)前 alpha 或透明值
該方法主要是設(shè)置圖形的透明度,這里就不具體介紹。
globalCompositeOperation: 設(shè)置或返回新圖像如何繪制到已有的圖像上,該方法有以下屬性值:
值 | 描述 |
---|---|
source-over | 在目標(biāo)圖像上顯示源圖像(默認(rèn)) |
source-atop | 在目標(biāo)圖像頂部顯示源圖像。源圖像位于目標(biāo)圖像之外的部分是不可見的 |
source-in | 在目標(biāo)圖像中顯示源圖像。只有目標(biāo)圖像之內(nèi)的源圖像部分會顯示,目標(biāo)圖像是透明的 |
source-out | 在目標(biāo)圖像之外顯示源圖像。只有目標(biāo)圖像之外的源圖像部分會顯示,目標(biāo)圖像是透明的 |
destination-over | 在源圖像上顯示目標(biāo)圖像 |
destination-atop | 在源圖像頂部顯示目標(biāo)圖像。目標(biāo)圖像位于源圖像之外的部分是不可見的 |
destination-in | 在源圖像中顯示目標(biāo)圖像。只有源圖像之內(nèi)的目標(biāo)圖像部分會被顯示,源圖像是透明的 |
destination-out | 在源圖像之外顯示目標(biāo)圖像。只有源圖像之外的目標(biāo)圖像部分會被顯示,源圖像是透明的 |
lighter | 顯示源圖像 + 目標(biāo)圖像 |
copy | 顯示源圖像。忽略目標(biāo)圖像 |
xor | 使用異或操作對源圖像與目標(biāo)圖像進(jìn)行組合 |
下面是一個小示例,可以通過點擊改變組合效果:
圖形組合
讀者可以點擊標(biāo)簽來觀察不同的組合效果,效果如下:
剪輯區(qū)域:
clip()方法從原始畫布中剪切任意形狀和尺寸。
提示:一旦剪切了某個區(qū)域,則所有之后的繪圖都會被限制在被剪切的區(qū)域內(nèi)(不能訪問畫布上的其他區(qū)域)。您也可以在使用 clip() 方法前通過使用 save() 方法對當(dāng)前畫布區(qū)域進(jìn)行保存,并在以后的任意時間對其進(jìn)行恢復(fù)(通過 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(): 如果指定的點位于當(dāng)前路徑中,則返回 true,否則返回 false。
這里就不逐個舉例說明了。
看完上述內(nèi)容,你們掌握什么是HTML5 canvas繪圖的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!