canvas 的 2D context 可以繪制簡單的 2D 圖形。它的 2D context 坐標開始於 <canvas>
元素的左上角,原點坐標是(0,0)。所有的坐標值都基於這個原點,x 值越大表示越靠右,y 值越大表示越靠下。width 和 height 表示水平和垂直方向上可用的像素數。
1 填充和描邊
填充就是用指定的樣式填充圖形;而描邊就是給圖形的邊緣畫線。它們分別對應兩個屬性:fillStyle 和 strokeStyle。這兩個屬性的值可以是字符串、漸變對象或者模式對象。默認值都是 “#00000”。如果為它們指定表示顏色的字符串值,可以使用 CSS 中指定顏色值的任何格式(顏色名、十六進制碼、rgb、rgba、hsl 或 hsla):
var drawing = document.getElementById("drawing"); if (drawing.getContext) {//確定瀏覽器支持 canvas var context = drawing.getContext("2d"); var context = drawing.getContext("2d"); context.strokeStyle = "red"; context.fillStyle = "#0000ff"; }
2 繪制矩形
矩形是唯一一種直接可以在 2D context 中繪制的圖形。它有 3 種方法:fillRect()、strokeRect() 和 clearRect()。它們都接收 4 個 參數:矩形的 x 坐標、y 坐標、矩形的寬度以及高度,這些參數的單位都是像素。
fillRect() 會為矩形填充指定的顏色,顏色是通過 fillStyle 屬性進行設置的:
<canvas id="drawing" width="200" height="200">A drawing of something.</canvas> <script type="text/javascript"> var drawing = document.getElementById("drawing"); if (drawing.getContext) {//確定瀏覽器支持 canvas var context = drawing.getContext("2d"); //繪制紅色矩形 context.fillStyle = "#ff0000"; context.fillRect(10, 10, 50, 50); //繪制半透明的藍色矩形 context.fillStyle = "rgba(0,0,255,0.5)"; context.fillRect(30, 30, 50, 50); } </script>
因為第二個矩形是半透明的,所以你可以透過上面的藍色矩形看到下面的紅色矩形:
strokeRect() 會使用指定的顏色為矩形描邊,描邊的顏色是通過 strokeStyle 指定的:
<script type="text/javascript"> var drawing = document.getElementById("drawing"); if (drawing.getContext) {//確定瀏覽器支持 canvas var context = drawing.getContext("2d"); //繪制紅色描邊矩形 context.strokeStyle = "#ff0000"; context.strokeRect(10, 10, 50, 50); //繪制半透明的藍色描邊矩形 context.strokeStyle = "rgba(0,0,255,0.5)"; context.strokeRect(30, 30, 50, 50); } </script>
注意: lineWidth 屬性控制着描邊線條的寬度,它可以是任意整數。lineCap 屬性可以控制線條末端的形狀(平頭【butt】、圓頭【round】或方頭【squre】)。lineJoin 控制線條相交的方式(圓交【round】、斜角【bevel】或斜接【miter】)。
clearRect() 可以清除畫布上的矩形區域。它是通過把某一矩形區域變透明來實現的。通過繪制形狀然后在清除指定區域后,會生成很有意思的效果:
<script type="text/javascript"> var drawing = document.getElementById("drawing"); if (drawing.getContext) {//確定瀏覽器支持 canvas var context = drawing.getContext("2d"); //繪制紅色矩形 context.fillStyle = "#ff0000"; context.fillRect(10, 10, 50, 50); //繪制半透明的藍色矩形 context.fillStyle = "rgba(0,0,255,0.5)"; context.fillRect(30, 30, 50, 50); //在兩個矩形重疊的地方清除一個小矩形 context.clearRect(40,40,10,10); } </script>
3 繪制路徑
使用路徑可以繪制出很復雜的形狀和線條。必須先調用 beginPath() 方法,然后再通過以下方法來繪制路徑:
方法 | 說明 |
---|---|
arc(x, y, radius, startAngle, endAngle, counterclockwise) | 以 (x,y) 為圓心繪制一條弧線,它的半徑是 radius。startAngle 是起始角度,endAngle 是結束角度,它們的單位都是弧度。counterclockwise 表示起始和結束角度是否按逆時針方向計算。 |
arcTo(x1, y1, x2, y2, radius) | 從上一點開始繪制弧線,以給定的半徑(radius)穿過 (x1, y1),直到 (x2, y2) 為止。 |
bezierCurveTo(c1x, c1y, c2x, c2y, x, y) | 從上一點開始繪制曲線,以 (c1x, c1y) 和 (c2x, c2y) 為控制點,開始繪制曲線。 |
lineTo(x, y) | 從上一點開始繪制直線,到 (x, y) 為止。 |
moveTo(x, y) | 將繪圖的游標移動到 (x, y) ,只是移動不畫線。 |
quadraticCurveTo(cx, cy, x, y) | 從上一點開始繪制二次曲線,以 (cx, cy)作為控制點,到 (x, y) 為止。 |
rect(x, y, width, height) | 從點(x, y) 開始繪制矩形,width 和 height 分別代表寬和高,它繪制的是矩形路徑,而不是我們之前說過的矩形形狀。 |
創建路徑后,有這些選擇:
- 調用 closePath() 可以繪制一條連接到路徑起點的線條。
- 調用 fill() 可以填充路徑(fillStyle 指定的值)。
- 調用 stroke() 對路徑進行描邊(strokeStyle 指定的值)。
- 調用 clip() 在路徑上創建一個剪貼區域。
現在我們繪制一個不帶數字的鍾:
<script type="text/javascript"> var drawing = document.getElementById("drawing"); if (drawing.getContext) {//確定瀏覽器支持 canvas var context = drawing.getContext("2d"); //開始路徑 context.beginPath(); //繪制外圓 context.arc(100,100,99,0,2*Math.PI,false); //繪制內圓 context.moveTo(194,100);//避免出現從外圓移動到內圓,造成的多余線條 context.arc(100,100,94,0,2*Math.PI,false); //繪制分針 context.moveTo(100,100); context.lineTo(100,15); //繪制時鍾 context.moveTo(100,100); context.lineTo(35,100); //描邊路徑 context.stroke();//實際畫出路徑 } </script>
路徑是一種主要的繪圖方式,因為它能為要繪制的圖形進行更多的控制。
isPointInPath() 接收 x 和 y 坐標作為參數,可以用來判斷某一點是否位於路徑上。
可以利用路徑的 API 繪制出非常復雜的圖形。
4 繪制文本
繪制文本 有 fillText() 和 strokeText() 這兩個方法,它們可以接收 4 個參數:要繪制的文本字符串、x 坐標、y 坐標和最大像素寬度(可選),它們都有以下這些屬性:
屬性 | 說明 |
---|---|
font | 文本樣式、大小以及字體(CSS 的字體格式) |
textAlign | 文本對齊方式,有這些值:start、end、left、right 和 center。建議使用 start(從左到右) 和 end(從右到左)。 |
textBaseline | 文本的基線,有這些值:top、hanging、middle、alphabetic、ideographic 和 bottom。 |
這些屬性都有默認值。fillText() 使用 fillStyle 來繪制文本,strokeText() 使用 strokeStyle 來為文本描邊。fillText() 的頻率會更多,因為它模仿了在網頁中顯示的文本方式。現在我們在之前的鍾上繪制數字:
//繪制文本 context.font = "bold 14px Arial"; context.textAlign = "center"; context.textBaseline = "middle"; context.fillText("12", 100, 20);
如果把 textAlign 設置為 start,表示 x 坐標是在文本左端的位置;如果設置為 end,則表示 x 坐標是在文本右端的位置:
/** * 繪制文本 */ //正常 context.font = "bold 14px Arial"; context.textAlign = "center"; context.textBaseline = "middle"; context.fillText("12", 100, 20); //起點對齊 context.textAlign="start"; context.fillText("12",100,40); //終點對齊 context.textAlign="end"; context.fillText("12",100,60);
meansureText() 可以確定文本的大小,它接受一個參數,即要繪制的文本,它會返回 TextMetrics 對象。這個對象有一個 width 屬性。
meansureText() 會根據 font、textAlign 和 textBaseline 的值來計算指定文本的合適大小:
<script type="text/javascript"> var drawing = document.getElementById("drawing"); if (drawing.getContext) {//確定瀏覽器支持 canvas var context = drawing.getContext("2d"),fontSize=50, i,len; //draw a white rectangle context.strokeWidth=1; context.strokeStyle="#000000"; context.strokeRect(10,10,150,30); //default font setting context.font = fontSize + "px Arial"; context.textBaseline="top"; while (context.measureText("Hello world!").width > 140) { fontSize--; context.font = fontSize + "px Arial"; } context.fillText("Hello world!", 10, 10); context.fillText("Font size is " + fontSize + "px", 10, 50); } </script>
5 變換
通過變換,可以把變換后的圖像繪制到畫布上。創建繪制上下文時,會以默認值初始化變換矩陣。有這些方法:
方法 | 說明 |
---|---|
rotate(angle) | 圍繞原點旋轉圖像 angle 弧度。 |
scale(scaleX, scaleY) | 縮放圖像,x 方向上乘以 scaleX,y 方向上乘以 scaleY。參數的默認值都是 1.0。 |
translate(x, y) | 坐標原點(0,0)移動到(x,y)。 |
setTransform(m1_1, m1_2, m2_1, m2_2, dx, dy) | 將矩陣重置為默認狀態,然后再調用 transform()。 |
transform(m1_1, m1_2, m2_1, m2_2, dx, dy) | 修改變換矩陣,即乘上底下這樣的矩陣: |
現在我們把原點變換到表盤的中心,然后再繪制表針,這樣在同一方向上繪制線條就變成了一個簡單的數學問題咯(因為所有的的計算都是基於 (0,0)):
<script type="text/javascript"> var drawing = document.getElementById("drawing"); if (drawing.getContext) {//確定瀏覽器支持 canvas var context = drawing.getContext("2d"); //開始路徑 context.beginPath(); //繪制外圓 context.arc(100,100,99,0,2*Math.PI,false); //繪制內圓 context.moveTo(194,100);//避免出現從外圓移動到內圓,造成的多余線條 context.arc(100,100,94,0,2*Math.PI,false); //變換原點 context.translate(100,100); //繪制分針 context.moveTo(0,0); context.lineTo(0,-85); //繪制時鍾 context.moveTo(0,0); context.lineTo(-65,0); //描邊路徑 context.stroke();//實際畫出路徑 } </script>
還可以使用 rotate() 來旋轉時鍾的表針:
<script type="text/javascript"> var drawing = document.getElementById("drawing"); if (drawing.getContext) {//確定瀏覽器支持 canvas var context = drawing.getContext("2d"); //開始路徑 context.beginPath(); //繪制外圓 context.arc(100,100,99,0,2*Math.PI,false); //繪制內圓 context.moveTo(194,100);//避免出現從外圓移動到內圓,造成的多余線條 context.arc(100,100,94,0,2*Math.PI,false); //變換原點 context.translate(100,100); //旋轉表針 context.rotate(1); //繪制分針 context.moveTo(0,0); context.lineTo(0,-85); //繪制時鍾 context.moveTo(0,0); context.lineTo(-65,0); //描邊路徑 context.stroke();//實際畫出路徑 } </script>
有兩種方法可以跟蹤狀態變化。一個是 save() 方法,它會把當時的所有設置放入一個棧結構。如果想要回到之前的設置,可以調用另一個方法 restore() ,它會恢復之前的狀態(在棧結構中返回一級)。多次調用 save() 會把多個設置都保存到棧結構中,如果這時再連續調用 restore() 方法,則會一級一級地返回設置:
<script type="text/javascript"> var drawing = document.getElementById("drawing"); if (drawing.getContext) {//確定瀏覽器支持 canvas var context = drawing.getContext("2d"); context.fillStyle = "#ff0000"; context.save(); context.fillStyle = "#00ff00"; context.translate(100, 100); context.save(); context.fillStyle = "#0000ff"; context.fillRect(0, 0, 100, 200);//從點(100,200)開始繪制藍色矩形 context.restore(); context.fillRect(10, 10, 100, 200);//從點(110,110)開始繪制綠色矩形 context.restore(); context.fillRect(0, 0, 100, 200);//從點(0,0)開始繪制紅色矩形 } </script>
注意:save() 只會保存繪圖上下文的設置和變換,但不會保存繪圖上下文的內容。
6 繪制圖像
使用 drawImage() 可以把圖像繪制到畫布中。可以傳入 HTML 的 <img>
元素,以及繪制該圖像的起點的 x 和 y 坐標;還可以再加上兩個參數(目標寬度和目標高度),這可以改變繪制后的圖像大小;實際上還可以把圖像的某個區域繪制到上下文中,這需要傳入 9 個參數:要繪制的圖像、源圖像的 x、y 坐標、源圖像的寬度和高度、目標圖像的 x、y 坐標、目標圖像的寬度和高度:
<canvas id="drawing" width="200" height="200">A drawing of something.</canvas> <img id="smiley" src="smile.gif" border="1" title="Image tag"/> <script type="text/javascript"> window.onload = function () {//必須在 onload 內運行才有效 var drawing = document.getElementById("drawing"); if (drawing.getContext) {//確定瀏覽器支持 canvas var context = drawing.getContext("2d"); var image = document.getElementById("smiley"); //draw regular size context.drawImage(image, 10, 10); //draw smaller size context.drawImage(image, 50, 10, 20, 30); //draw just part of the image context.drawImage(image, 0, 10, 50, 50, 0, 100, 40, 60); } }; </script>
還可以傳入另一個 <canvas>
元素作為 drawImage() 方法的第一個參數,這樣就可以把另一個畫布內容繪制到當前的畫布上。
drawImage() 的操作結果可以通過 toDataURL() 得到,但這個圖像不能來自其他域。還有,這個 toDataURL() 是 Canvas 對象上的方法!
# 7 陰影
有這些方法可以為形狀或路徑繪制陰影:
方法 | 說明 |
---|---|
shadowColor | 陰影顏色,CSS 的顏色格式,默認為黑色。 |
shadowOffsetX | 形狀或路徑 x 軸方向上的陰影偏移量,默認為 0。 |
shadowOffsetY | 形狀或路徑 y 軸方向上的陰影偏移量,默認為 0。 |
shadowBlur | 模糊的像素數,默認為0,即不模糊。 |
它們都可以通過 context 對象進行修改,只要在繪制前為它們設置值,就能生成陰影:
“`
A drawing of something.
var drawing = document.getElementById("drawing"); if (drawing.getContext) {//確定瀏覽器支持 canvas var context = drawing.getContext("2d"); //設置陰影 context.shadowOffsetX = 5; context.shadowOffsetY = 5; context.shadowBlur = 4; context.shadowColor = "rgba(0,0,0,0.5)"; //繪制紅色矩形 context.fillStyle = "#ff0000"; context.fillRect(10, 10, 50, 50); //繪制半透明的藍色矩形 context.fillStyle = "rgba(0,0,255,0.5)"; context.fillRect(30, 30, 50, 50); }
“`
8 漸變
使用 CanvasGradient 實例可以創建一個新的線性漸變,然后調用 createLinearGradient() ,它接收 4 個參數:起點的 x、y 坐標、終點的 x、y 坐標,它會創建一個指定大小的漸變,然后返回 CanvasGradient 實例。
創建漸變對象后,可以使用 addColorStop() 來指定色標。它接受 2 個參數:色標的位置(0 ~ 1)以及 CSS 顏色值。接着可以把 fillStyle 或 strokeStyle 設置為這個對象,使用漸變來繪制形狀或者描邊:
<script type="text/javascript"> var drawing = document.getElementById("drawing"); if (drawing.getContext) {//確定瀏覽器支持 canvas var context = drawing.getContext("2d"); //繪制紅色矩形 context.fillStyle = "#ff0000"; context.fillRect(10, 10, 50, 50); //創建漸變對象 var gradient = context.createLinearGradient(30, 30, 70, 70); gradient.addColorStop(0, "white"); gradient.addColorStop(1, "black"); //繪制漸變矩形 context.fillStyle = gradient; context.fillRect(30, 30, 50, 50); } </script>
如果漸變矩形沒有繪制到恰當的位置,那就只會顯示部分漸變效果:
... //繪制漸變矩形 context.fillStyle = gradient; context.fillRect(50, 50, 50, 50); ...
所以要確保漸變一定要與形狀對齊,因此可以可以使用函數來確定坐標處於合適的位置:
<script type="text/javascript"> function createRectLinearGradient(context, x, y, width, height) { return context.createLinearGradient(x, y, x + width, y + height); } var drawing = document.getElementById("drawing"); if (drawing.getContext) {//確定瀏覽器支持 canvas var context = drawing.getContext("2d"); //繪制紅色矩形 context.fillStyle = "#ff0000"; context.fillRect(10, 10, 50, 50); //創建漸變對象 var gradient = createRectLinearGradient(context,30, 30, 50, 50); gradient.addColorStop(0, "white"); gradient.addColorStop(1, "black"); //繪制漸變矩形 context.fillStyle = gradient; context.fillRect(30, 30, 50, 50); } </script>
createRectLinearGradient() 函數是基於起點的 x 和 y 坐標以及寬度和高度來創建漸變對象的,這樣就可以在 fillRect() 中使用相同的值。
createRadialGradient() 可以創建徑向漸變,即放射漸變。它接受 6 個參數:對應兩個圓的圓心和半徑,即起點圓的圓心(x、y)和半徑,以及終點圓的圓心(x、y)和半徑。
如果要從某個形狀的中心點創建一個向外擴散的徑向漸變,就必須把這兩個圓定義為同心圓:
<script type="text/javascript"> var drawing = document.getElementById("drawing"); if (drawing.getContext) {//確定瀏覽器支持 canvas var context = drawing.getContext("2d"); var gradient = context.createRadialGradient(55, 55, 10, 55, 55, 30); gradient.addColorStop(0, "white"); gradient.addColorStop(1, "black"); //繪制紅色矩形 context.fillStyle = "#ff0000"; context.fillRect(10, 10, 50, 50); //繪制漸變矩形 context.fillStyle = gradient; context.fillRect(30, 30, 50, 50); } </script>
9 模式
模式就是重復的圖像,可以利用模式來填充或者描邊圖形。createPattern() 會創建一個模式,它接受 2 個參數:一個 HTML 的 <img>
元素以及如何重復圖像(與 CSS 的 background-repeat 屬性值一致,即 repeat\repeat-x\repeat-y\no-repeat):
<script type="text/javascript"> window.onload = function () {//放在這里,才有效 var drawing = document.getElementById("drawing"); if (drawing.getContext) {//確定瀏覽器支持 canvas var context = drawing.getContext("2d"); var image = document.images[0], pattern = context.createPattern(image, "repeat"); //繪制矩形 context.fillStyle = pattern; context.fillRect(10, 10, 150, 150); } }; </script>
createPattern() 的第一個參數也可以是 <video>
元素或者是 <canvas>
元素。
10 使用圖像數據
使用 getImageData() 可以取得原始的圖像數據。它接受 4 個參數:圖像區域的 x、y 坐標以及該區域的像素高度與寬度。它返回 ImageData 實例。
ImageData 實例有三個屬性:width、height 和 data。data 是數組,它保存着圖像中每一個像素的數據。每一個像素的數據包含 4 個元素它們是紅、綠、藍和透明度值。這些值都介於 0 到 255 之間。
可以修改圖像的數據,創建一個簡單的灰階過濾器:
<canvas id="drawing" width="200" height="200">A drawing of something.</canvas> <img id="smiley" src="smile2.gif" border="1" title="Image tag"> <script type="text/javascript"> window.onload = function () { var drawing = document.getElementById("drawing"); if (drawing.getContext) {//確定瀏覽器支持 canvas var context = drawing.getContext("2d"), image = document.images[0], imageData, data, i, len, average, red, green, blue, alpha; //繪制原始圖像 context.drawImage(image, 0, 0); //取得圖像數據 imageData = context.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]; //求得 rgb 平均值 average = Math.floor((red + green + blue) / 3); //設置顏色值,透明度不變 data[i] = average; data[i + 1] = average; data[i + 2] = average; } //回寫圖像數據並顯示結果 imageData.data = data; context.putImageData(imageData, 0, 0); } }; </script>
注意上面的代碼必須運行於 web 服務器(如果是 chrome),而且只對 gif 圖像有效!
* 注意:* 只有在畫布中的圖像都是來源於同一個域時,才可以取得圖像數據!否則會報 JavaScript 錯誤。
11 合成
globalAlpha 屬性可以指定透明度,它的值介於 0 到 1,默認是 0.如果所有后續的操作都要基於同樣的透明度,那就可以先設置 globalAlpha 屬性,然后再繪制,最后再設置為默認值:
<script type="text/javascript"> window.onload = function () { var drawing = document.getElementById("drawing"); if (drawing.getContext) {//確定瀏覽器支持 canvas var context = drawing.getContext("2d"); //繪制紅色矩形 context.fillStyle = "#ff0000"; context.fillRect(10, 10, 50, 50); //修改全局透明度 context.globalAlpha = 0.5; //繪制藍色矩形 context.fillStyle = "rgba(0,0,255,1)"; context.fillRect(30, 30, 50, 50); //重置全局透明度 context.globalAlpha = 0; } }; </script>
globalCompositionOperation 屬性用於指定后繪制的圖形與新繪制的圖形的結合方式,值是字符串,有這些:
屬性值 | 說明 |
---|---|
source-over | 后繪制的圖形在先繪制的圖形的上方,默認。 |
source-in | 后繪制的圖形與先繪制的圖形重疊的部分可見,其他部分透明。 |
source-out | 后繪制的圖形與先繪制的圖形不重疊的部分可見,先繪制的圖形透明。 |
source-atop | 后繪制的圖形與先繪制的圖形重疊的部分可見,先繪制的圖形不受影響。 |
destination-over | 后繪制的圖形在先繪制的圖形的下方,只有先繪制的圖形的透明下的部分才可見。 |
destination-in | 后繪制的圖形在先繪制的圖形的下方,不重疊的部分透明。 |
destination-out | 后繪制的圖形擦除先繪制圖形的重疊部分。 |
destination-atop | 后繪制的圖形在先繪制的圖形的下方,不重疊的部分,先繪制的圖形透明。 |
lighter | 后繪制的圖形與先繪制的圖形的重疊部分值相加,即變亮。 |
copy | 后繪制的圖形完全代替先繪制的圖形的重疊部分。 |
xor | 后繪制的圖形與先繪制的圖形在重疊部分執行“異或”操作。 |
<script type="text/javascript"> window.onload = function () { var drawing = document.getElementById("drawing"); if (drawing.getContext) {//確定瀏覽器支持 canvas var context = drawing.getContext("2d"); //繪制紅色矩形 context.fillStyle = "#ff0000"; context.fillRect(10, 10, 50, 50); //設置合成操作 context.globalCompositeOperation="destination-over"; //繪制藍色矩形 context.fillStyle = "rgba(0,0,255,1)"; context.fillRect(30, 30, 50, 50); //重置全局透明度 context.globalAlpha = 0; } }; </script>
使用 globalCompositionOperation 屬性時,請一定要多測試一些瀏覽器,因為不同的瀏覽器可能在實現這個屬性時存在較大的差異!
轉載自--csdn
覺得好就拿來了