HTML Canvas基本概念
Canvas元素是HTML5新家的元素,這個元素負責在頁面中設定一個區域,然後就可以通過Javascript動態地在這個區域中繪制圖形
基本用法
使用canvas元素時,必須先設置其width
屬性和height
屬性,指定繪圖區域的大小。出現在canvas標簽中的內容是後備信息,如果瀏覽器不支持canvas元素,就會顯示這些信息。
<canvas id="canvas" width="300" height="200">
您的瀏覽器不支持Canvas
</canvas>
要在這塊畫布上繪圖,就需要獲得其繪圖上下文,取得繪圖上下文對象的引用,需要調用getContext()
2d
,就可以獲得2D上下文對象,也可以傳入webgl
獲得webgl上下文的對象。
var canvas = document.getElementById("canvas"); if (canvas.getContext) { var ctx = canvas.getContext(‘2d‘); } //在使用canvas元素之前,首先要檢測是否有getContext()方法,有些瀏覽器會將HTML規範之外的元素創建為默認的HTML元素對象,這種情況下,即使獲取了id為canvas的元素,也不一定是canvas元素,沒有getContext()方法。
使用toDataURL()
方法,可以將canvas元素上繪制的圖像導出,這個方法接收一個參數,即圖像的MIME類型,而且適用於創建圖像的任何上下文。
var canvas = document.getElementById(‘canvas‘); if (canvas.getContext) { //獲取圖像的數據URI var imgURL = canvas.toDataURL(‘img/png‘); //顯示圖像 var image = document.createElement(‘img‘); image.src = imgURL; document.body.appendChild(image); }
2D上下文
使用2D繪圖上下文提供的方法。可以繪制簡單的2D圖形,如矩形、弧線和路徑。2D上下文的坐標開始於canvas元素的左上角,坐標原點是(0,0),水平方向代表x軸,向右為正,豎直方向表示y軸,向下為正。
填充和描邊
填充就是用指定的樣式(顏色、漸變或圖像)填充圖形,這個操作可以使用strokeStyle
屬性來指定樣式。
描邊就是在圖形的邊緣劃線,這個操作使用fillStyle
屬性來指定樣式。fillStyle
和strokeStyle
屬性的值可以是字符串、漸變對象或模式對象,其默認值是#000000,如果使用表示顏色的字符串值,可以使用CSS中指定顏色值的任何形式,十六進制碼、rgb、rgba、hsl、hsla等。
ctx.strokeStyle = "red"; //指定描邊顏色
ctx.fillStyle = "#0000ff"; //指定填充顏色
繪制矩形
2D上下文對象可以直接繪制矩形,其方法有:
- fillRect(x, y, width, height):繪制左上角坐標為(x,y), 寬為width,高為height的矩形,並按fillStyle指定的模式填充
- strokeRect(x, y, width, height):繪制左上角坐標為(x, y), 寬為width,高為height的矩形,並按strokeStyle指定的模式描邊
- clearRect(x, y, width, height):清除矩形區域,實際上是把一部分區域變得透明。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>繪制矩形</title>
</head>
<body>
<canvas id="canvas" height="600" width="1200"></canvas>
</body>
<script type="text/javascript">
var canvas = document.getElementById("canvas")
if (canvas.getContext) {
var ctx = canvas.getContext(‘2d‘)
ctx.fillStyle = "#ff0000"
ctx.strokeStyle = "#00ff00"
ctx.fillRect(10,10,50,50)
ctx.strokeRect(70,70,50,50)
ctx.fillRect(200,200,300,300)
ctx.fillStyle = "#0000ff"
ctx.fillRect(300,300,300,300)
ctx.clearRect(350,350,100,100)
}
</script>
</html>
運行效果:
描邊線條的寬度可以使用lineWidth
屬性來控制,其屬性值可以為任意的額整數,還可以使用lineCap
屬性控制線條末端的形狀是平頭(butt
)、圓頭(round
)還是方頭(square
),lineJoin
屬性可以控制蕭條相交的方式是圓交(round
)、斜交(bevel
)還是斜接(miter
)。
繪制路徑
canvas使用一種基於狀態的方式來繪圖,意思就是,你繪圖的結果取決於你當前設置的狀態,我們上面使用了strokeStyle
和fillStyle
規定了描邊和填充的顏色,當我們再次給這兩個屬性賦予了新的值之後,再繪制的圖形的填充顏色和描邊顏色就會跟著發生改變。在繪制路徑時,可以先設置好一段路徑的屬性,比如上面提的strokeStyle
,fillStyle
,lineWidth
等,然後開始繪制路線,最後決定以填充方式或者描線方式繪制該路徑,然後在規定新的路徑的屬性。
要繪制路徑,首先要調用beginPath()
方法,表示開始繪制新路徑,然後使用下面的方法繪制該路徑:
- arc(x, y, radius, startAngle, endAngle, counterclockwise):以(x,y)為圓心繪制一條弧線,弧線的半徑為radius,其實角度(用弧度表示)分別為startAngle和endAngle,最後一個參數表示是否用按逆時針方向計算,為false時表示按順時針計算。
- arcTo(x1, y1, x2, y2, radius):從上一點開始繪制一條弧線,到(x2, y2)為止,並且給指定的半徑radius穿過點(x1, y1)。
- bezierCurveTo(c1x, c1y, c2x, c2y, x, y):從上一點開始繪制一條曲線,到(x, y)為止,並且經過(c1x, c1y)和(c2x, c2y)兩點。
- lineTo(x, y):從上一點繪制一條直線,到(x, y)為止。
- moveTo(x, y):將當前的畫筆移動到(x, y),不繪制路徑。
- quadraticCurveTo(cx, cy, x, y):從上一點開始繪制一條二次曲線,到(x, y)為止,並經過(cx, cy)。
- rect(x, y, width, height):從(x, y)開始繪制一個矩形,寬高分別為width和height。
路徑繪制結束後,使用closePath()
方法結束繪制路徑。然後用stroke()
或fill()
方法繪制線或者填充,也可以用‘clip()‘方法創建一個剪切區域。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>繪制路徑</title>
</head>
<body>
<canvas id="canvas" width="1200" height="600"></canvas>
</body>
<script type="text/javascript">
var canvas = document.getElementById(‘canvas‘)
if (canvas.getContext) {
var ctx = canvas.getContext(‘2d‘)
ctx.strokeStyle = ‘red‘
ctx.beginPath()
ctx.arc(100, 100, 100, 0, Math.PI / 2,true)
ctx.stroke()
ctx.closePath()
ctx.strokeStyle = ‘green‘
ctx.beginPath()
ctx.moveTo(100,200)
ctx.arcTo(200,300,100,400,100)
ctx.stroke()
ctx.closePath()
ctx.strokeStyle = "yellow"
ctx.beginPath()
ctx.bezierCurveTo(100,200,300,200,400,400)
ctx.stroke()
ctx.closePath()
ctx.strokeStyle = "blue"
ctx.beginPath()
ctx.moveTo(500,200)
ctx.quadraticCurveTo(100,300,600,600)
ctx.stroke()
ctx.closePath()
ctx.strokeStyle = "orange"
ctx.beginPath()
ctx.rect(200,200,200,300)
ctx.stroke()
ctx.closePath()
}
</script>
</html>
結果:
*在這註意,arc()
方法中,x的正方向,即水平向右方向的角度為0,然後順時針方向增加,y正方向,即垂直向下方向為90度,水平左方向為180度,垂直向上方向為270度,再次到水平向右方向時,是360度,所以,想創建一個整圓,可以這麽寫:`ctx.arc(100,100,100,0,Math.PI 2,true)`**
關於closePath()
,還有另一作用,如果調用了closePath()
之後再執行stroke()
,圖形將自動閉合,否則不會閉合。如下面的例子所示:
ctx.beginPath()
ctx.arc(100,100,100,0,Math.PI / 2, true);
ctx.closePath()
ctx.stroke()
結果:
繪制文本
2D上下文也提供了繪制文本的方法,繪制文本主要有兩個方法:
- fillText(str, x, y, ?width)
- strokeText(str, x, y, ?width)
這兩個方法都有四個參數:要繪制的文本的字符串,x坐標,y坐標,可選的參數,最大像素寬度。這兩個方法都以下面三個屬性為基礎:
- font:表示文本樣式、大小及字體,可以使用css中指定字體的格式來指定,如"10px Arial"
- textAlign:表示文本的對齊方式,可能的值有"start","end","left","right"和"center",其中"start"和"left","end"和"right"的效果一樣,但是建議前者。
- textBaseline:表示文本的基線,可能的值有"top",“hanging”,"middle","alphabetic","ideographic"和"bottom"
實際上,textAlign
和textBaseline
分別決定了文本的水平對齊方式和豎直對齊方式。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>繪制文本</title>
</head>
<body>
<canvas id="canvas" width="300" height="300"></canvas>
</body>
<script type="text/javascript">
var canvas = document.getElementById(‘canvas‘)
if (canvas.getContext){
var ctx = canvas.getContext(‘2d‘)
ctx.beginPath()
ctx.moveTo(100,0)
ctx.lineTo(100,100)
ctx.closePath()
ctx.stroke()
ctx.font = "20px Times New Roman"
ctx.textAlign = "start"
ctx.textBaseline = "middle"
ctx.fillText("canvas",100,10)
ctx.textAlign = "end"
ctx.fillText("canvas",100,25)
ctx.textAlign = "center"
ctx.fillText("canvas",100,40)
}
</script>
</html>
運行結果:
變換
通過上下文的變換,可以將處理後的圖像繪制到畫布上,創建繪制上下文時,會以默認值初始化變換矩陣,使用變換時,會使用不同的變換矩陣來做處理,產生不同的效果。
可以使用以下方法來修改變換矩陣:
- rotate(angle):圍繞原點旋轉angle弧度
- scale(scaleX, scaleY):縮放圖像,在x方向乘以scaleX,在y方向乘以scaleY
- translate(x,y):將坐標原點移動到(x,y)
- transform(m1_1,m1_2,m2_1,m2_2,dx,dy):直接修改變換矩陣,方式是乘以以下矩陣:\begin{bmatrix} m1_1 & m1_2 & dx\m2_1 & m2_2 & dy \ 0 & 0 & 1 \end{bmatrix}
- setTranform(m1_1,m1_2,m2_1,m2_2,dx,dy):將變換矩陣重置為默認值,然後調用transform()
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>變換</title>
</head>
<body>
<canvas id="canvas" width="1200" height="600"></canvas>
</body>
<script type="text/javascript">
var canvas = document.getElementById("canvas")
if (canvas.getContext) {
var ctx = canvas.getContext(‘2d‘)
ctx.strokeStyle = "red"
ctx.rotate(-Math.PI/6)
ctx.beginPath()
ctx.rect(200,400,200,100)
ctx.stroke()
ctx.closePath()
ctx.strokeStyle = "blue"
ctx.rotate(Math.PI/6)//將上面的30度恢復原狀
ctx.scale(1,2)
ctx.beginPath()
ctx.rect(100,100,200,100)
ctx.stroke()
ctx.closePath()
ctx.strokeStyle = "green"
ctx.setTransform(1,0,2,1,0,0)//對-45度對稱
ctx.beginPath()
ctx.rect(100,100,100,100)
ctx.stroke()
ctx.closePath()
}
</script>
</html>
運行結果:
繪制圖像
2D上下文對象提供了對圖像的支持,如果想在畫布上繪制一幅圖像,可以使用drawImage()方法,這個方法的參數根據需要,有幾種可能。
-
傳入一個<img>元素,以及繪制該圖像的起點的x和y坐標
var image = document.images[0] ctx.drawImage(image,10,10)
-
img元素,圖像起點x,y,目標圖像寬度和高度
ctx.drawImage(image, 50, 10 20 30)
- 要繪制的圖像、源圖像的x坐標、源圖像的y坐標、源圖像的寬度、源圖像的高度、目標圖像的x坐標、目標圖像的y坐標、目標圖像的寬度、目標圖像的高度。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>繪制圖像</title>
<style type="text/css">
img{display: block; padding: 5px;border: 1px solid black;margin-bottom: 15px;}
</style>
</head>
<body>
<img src="cat.jpg">
<canvas id="canvas" width="600" height="600"></canvas>
</body>
<script type="text/javascript">
var img = document.images[0]
var canvas = document.getElementById("canvas")
if (canvas.getContext) {
var ctx = canvas.getContext(‘2d‘)
ctx.drawImage(img, 0, 0)
ctx.drawImage(img, 300, 0, 120, 100)
ctx.drawImage(img,40,40,150,150,450,0,160,80)
}
</script>
</html>
運行結果:
陰影
2D上下文會根據以下幾個屬性的值,自動為形狀或路徑繪制出陰影。
- shadowColor:用CSS顏色格式表示的陰影顏色,默認為黑色
- shadowOffsetX:形狀或路徑x軸方向的陰影偏移量,默認為0
- shadowOffsetY:形狀或路徑y軸方向的陰影偏移量,默認為0
- shadowBlur:模糊的像素數,默認為0
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>陰影</title>
</head>
<body>
<canvas id="canvas" width="1200" height="600"></canvas>
</body>
<script type="text/javascript">
var canvas = document.getElementById("canvas")
if (canvas.getContext) {
var ctx = canvas.getContext(‘2d‘)
ctx.shadowOffsetX = 5
ctx.shadowOffsetY = 5
ctx.shadowBlur = 5
ctx.shadowColor = "rgba(0,0,0,0.5)"
ctx.fillStyle = "#ff0000"
ctx.fillRect(10,10,50,50)
}
</script>
</html>
運行結果
漸變
漸變由CanvasGradient實例表示,可以通過2D上下文來創建和修改。
創建線性漸變可以使用createLinearGradient()
方法,這個方法有四個參數:起點的x坐標、起點的y坐標、終點的x坐標、終點的y坐標。
創建了漸變對象之後,可以使用addColorStop()
方法來指定色標,這個方法接收兩個參數:色標位置和CSS顏色值,色標位置是一個0(開始的顏色)-1(結束的顏色)之間的數字。
最後,將fillStyle或strokeStyle設置為這個對象,從而使用漸變色來繪制形狀或描邊。
創建徑向漸變時,可以使用createRadialGradient()
方法,這個方法接收6個參數,對應著兩個圓的圓心即半徑。前三個參數指定的是起點圓的圓心坐標x,y和半徑,後三個參數指終點圓的圓心坐標x,y即半徑。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>漸變</title>
</head>
<body>
<canvas id="canvas" width="1200" height="600"></canvas>
</body>
<script type="text/javascript">
var canvas = document.getElementById("canvas")
if (canvas.getContext) {
var ctx = canvas.getContext(‘2d‘)
var linearGardient = ctx.createLinearGradient(30,30,70,70)
var radialGardient = ctx.createRadialGradient(155,155,10,150,150,30)
linearGardient.addColorStop(0,"red")
linearGardient.addColorStop(1,"yellow")
radialGardient.addColorStop(0,"blue")
radialGardient.addColorStop(1,"green")
ctx.fillStyle = "#ff0000"
ctx.fillRect(10,10,50,50)
ctx.fillStyle = linearGardient
ctx.fillRect(30,30,50,50)
ctx.fillRect(50,50,50,50)
ctx.fillStyle = "#0000ff"
ctx.fillRect(110,110,50,50)
ctx.fillStyle = radialGardient
ctx.fillRect(130,130,50,50)
}
</script>
</html>
運行結果:
模式
模式就是重復的圖像,可以用來填充或者描邊推行。
創建新模式:createPattern()
,參數有兩個:一個img元素,一個表示如何重復圖像的字符串,其中,第二個參數的值與css的background-repeat屬性值相同,包括repeat
,repeat-x
,repeat-y
和no-repeat
var image = document.images[0],
pattern = ctx.createPattern(image, "repeat")
ctx.fillStyle = pattern
ctx.fillRect(10,10,150,150)
使用圖像數據
2D上下文可以使用getImageData()
取得原始圖像的數據,這個方法接收4個參數:要取得其數據的畫圖區域的x和y坐標,以及該區域像素的高度和寬度。var imageData = context.getImageData(10,5,150,150)
其返回對象是ImageData的實例,每個ImageData對象都有三個屬性:width,height和data,data是一個數組,保存著圖像中每一個像素的數據,在data數組中,每一個像素用4個元素來保存,分別表示紅綠藍和透明度值。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>獲取圖像數據</title>
<style type="text/css">
img{border:1px solid black; display: block;margin-bottom: 15px;}
</style>
</head>
<body>
<img src="cat.jpg">
<canvas id="canvas" width="1200" height="600"></canvas>
</body>
<script type="text/javascript">
var canvas = document.getElementById("canvas")
if (canvas.getContext) {
var ctx = canvas.getContext(‘2d‘),
image = document.images[0],
imageData, data,
i, len, average,
red, green, blue, alpha
//繪制原始圖像
ctx.drawImage(image, 0, 0)
//取得圖像數據
imageData = ctx.getImageData(0,0,image.width,image.height)
data = imageData.data
for (i = 0, len = data.length; i < len; i += 4) {
red = data[i]
green = data[i + 1]
blue = data[i + 2]
alpha = data[i + 3]
average = Math.floor((red + green + blue) / 3)
data[i] = average
data[i + 1] = average
data[i + 2] = average
}
imageData.data = data
ctx.putImageData(imageData,300,0)
}
</script>
</html>
運行結果
合成
還有兩個會應用到2D上下文中所有繪制操作的屬性
- globalAlpha:一個介於0-1的值,用於指定所有繪制的透明度,默認為0,如果所有後續操作都要基於相同的透明度,就可以先把globalAlpha設置為適當的值,然後繪制,最後再把它設置成默認值0
- globalCompositionOpreation:表示後繪制的圖形怎樣與先繪制的圖形結合,這個屬性的值是字符串,可能的值如下:
- source-over:默認值,後繪制的圖形位於先繪制的圖形上方
- source-in:後繪制的圖形與先繪制的圖形重疊部分課件,兩者其他部分全部透明
- source-out:後繪制的圖形與先繪制的圖形不重疊的部分課件,兩者其他部分完全透明
- source-atop:後繪制的圖形與先繪制的圖形重復部分可見,先繪制圖形不受影響
- destination-over:後繪制的圖形位於先繪制的圖形下方,只有之前透明像素下的部分才可見
- destination-in:後繪制的圖形位於先繪制的圖形下方,兩者不重疊的部分完全透明
- destination-out:後繪制的圖形擦除與先繪制的圖形的重疊部分
- destionation-atop:後繪制的圖形位於先繪制的圖形下方,兩個不重疊的地方,先繪制的圖形會完全透明
- lighter:後繪制的圖形與先繪制的圖形重疊部分的值相加,使該部分變亮
- copy:後繪制的圖形完全替代與之重疊的先繪制圖形
- xor:後繪制的圖形與先繪制的圖形重疊的部分執行“異或”操作
HTML Canvas基本概念