canvas簡介
canvas標籤是HTML5標準最受歡迎的一個標籤,它的作用就相當於一塊畫布,可以通過JS腳本在canvas上面進行繪畫,而且還可以對畫面的內容進行修改,通過不斷修改可以實現動畫的效果,再跟事件結合後就可以製作遊戲了!
canvas標籤及其所對應的JS對象HTMLCanvasElement本身非常簡單,它們主要包含width、height兩個屬性和一個getContext方法。雖然HTML5中新增了setContext等方法,但是各大瀏覽器支持得並不好。
canvas本身並沒有太多得操作,它主要是通過getContext方法獲取的環境對象進行操作。canvas和它所包含的context對象的關係就好像canvas是一塊畫布,而context是各種筆,拿到筆,然後纔可以繪圖。
canvas的用法
首先獲取canvas對象,然後使用這個對象獲取相應的環境,最後使用獲取的環境繪圖。
代碼示例:
<body>
<canvas id="c2d" width="300" height="300">瀏覽器不支持canvas</canvas>
<canvas id="c3d" width="150" height="150">瀏覽器不支持canvas</canvas>
<script>
// 獲取canvas對象
const canvas2d = document.querySelector('#c2d');
// 使用這個對象獲取相應的環境
const ctx2d = canvas2d.getContext('2d');'
// 繪製圖形...
const canvas3d = document.querySelector('#c3d');
const ctx3d = canvas3d.getContext('webgl');
</script>
</body>
從示例中,我們可以看出利用getContext()方法獲取繪圖環境,目前只支持2d('2d')和3d('webgl')環境。
繪製矩形
繪製矩形是canvas中最簡單的功能,跟繪製矩形相關的方法一共包括如下三個:
- strokeRect(x,y,width,height):繪製矩形邊框
- fillRect(x,y,width,height):繪製矩形並填充
-
clearRect(x,y,width,height): 清除矩形區域內容,實際上是使用底色填充矩形區域。
這三個方法的參數中,x,y表示矩形左上角的座標,width和height表示矩形的寬和高,座標原點默認爲canvas的左上角,canvas中矩形的結構如下:
代碼示例:
<canvas id="c2d" width="300" height="300">瀏覽器不支持canvas</canvas>
<script>
const canvas2d = document.querySelector('#c2d');
const ctx2d = canvas2d.getContext('2d');
// 繪製矩形
ctx2d.fillRect(30,50,100,50);
ctx2d.strokeRect(100,30,100,50);
ctx2d.clearRect(101,51,28,28);
</script>
繪製路徑
使用路徑一共可以分爲4步:創建路徑、繪製路徑、關閉路徑和操作路徑,其中繪製路徑最複雜也是最重要的內容。先介紹其他三種操作,最後詳細講解繪製路徑。
創建/關閉路徑
創建路徑
路徑的創建一共有兩種方法,一種是調用CanvasRenderingContext2D的beginPath方法,另一種是新建Path2D對象。
調用CanvasRenderingContext2D的beginPath方法後就可以直接使用CanvasRenderingContext2D來繪製路徑,而使用Path2D新建時會返回新建的路徑,然後在新建出來的路徑上進行操作,例如下面的例子:
<canvas id="c2d">瀏覽器不支持canvas</canvas>
<script>
const c2d = document.querySelector('#c2d');
const ctx2d = c2d.getContext('2d');
// 使用beginPath方法創建
ctx2d.beginPath();
// 這裏可以使用ctx2d繪製路徑
// ......
// 使用Path2D新建路徑
const newPath = new Path2D();
// 這裏實際newPath來繪製路徑
//......
</script>
關閉路徑
關閉路徑使用的是closePath方法,其主要作用是將路徑閉合起來,也就是從畫筆的終點到路徑的起點繪製一條直線,如果路徑已經閉合,那麼也可以不調用該方法。
操作路徑
對路徑的操作只有兩種:填充和描邊,它們所對應的方法分別是stroke和fill。如果是使beginPath創建的路徑,那麼直接調用就可以了,如果是新建的Path2D路徑,那麼需要將創建出來的路徑傳入參數中,例如下面的例子:
<canvas id="c2d">瀏覽器不支持canvas</canvas>
<script>
const c2d = document.querySelector('#c2d');
const ctx2d = c2d.getContext('2d');
// 使用beginPath方法創建
ctx2d.beginPath();
// 這裏可以使用ctx2d繪製路徑
// ......
ctx2d.closePath();
ctx2d.fill();
// 使用Path2D新建路徑
const newPath = new Path2D();
// 這裏實際newPath來繪製路徑
//......
newPath.closePath();
ctx2d.stroke(newPath);
</script>
繪製路徑
所有平面上的圖形都是由直線和曲線組成的(點其實是半徑很小的實心圓),因此路徑的繪製主要分爲直線和曲線兩種類型。但是,CanvasRenderingContext2D繪製路徑時除了這兩種類型外還有一個輔助操作的方法。
輔助操作
輔助方法:moveTo(x,y),兩個參數表示移動到的目標點的座標值
繪製直線
方法:lineTo(x,y),它可以從畫筆當前點到參數中傳入的座標點畫一條直線,一般會與moveTo方法配合使用。
樣式的設置
屬性:lineWidth:指定線條的寬度
屬性:lineDashOffset: 指定虛線的偏移量
方法:setLineDash():設置虛線的樣式,參數爲一個數組,數組的元素用來表示實線與空白所佔用的寬度,虛線會按數組中的值進行循環。
示例(畫一個正方形和兩條虛線):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<canvas id="canvas" width="500" width="500"></canvas>
<script>
const canvas = document.querySelector('#canvas');
if(canvas.getContext) {
const ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.lineWidth = 10;
ctx.moveTo(10,10);
ctx.lineTo(10,100);
ctx.lineTo(100,100);
ctx.lineTo(100,10);
ctx.closePath();
ctx.stroke();
ctx.beginPath();
ctx.lineWidth = 1;
ctx.setLineDash([5,10]);
ctx.moveTo(10,120);
ctx.lineTo(120,120);
ctx.closePath();
ctx.stroke();
ctx.beginPath();
ctx.setLineDash([5,10]);
ctx.lineDashOffset = 2;
ctx.moveTo(10,130);
ctx.lineTo(130,130);
ctx.closePath();
ctx.stroke();
}
</script>
</body>
</html>
繪製曲線
繪製圓弧
方法:arc(x,y,radius,startAngle,endAngle,anticlockwise)
參數說明:x,y爲圓心,radius爲半徑,startAngle和endAngle分別是起始角度和結束角度,anticlockwise表示是否逆時針繪製,默認爲順時針。
方法:arcTo(x1,y1,x2,y2,radius)
參數說明:通過兩條切線和半徑來指定一段圓弧,畫筆當前點和(x1,y1), (x1,y1)和(x2,y2)構成兩條切線,參數radius爲半徑。兩條切線和一個半徑可以將一個圓分成兩段圓弧,acrTo方法繪製的是較短的那段。如果畫筆的起始點不是圓弧的切點,那麼acrTo方法還會將起點和切點使用直線連接起來。
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<canvas width="500" height="500" id='c2d'></canvas>
<script>
const canvas = document.getElementById('c2d');
const ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.arc(100,100,100,0, 2*Math.PI,false);
ctx.closePath();
ctx.stroke();
ctx.beginPath();
ctx.lineTo(250,30);
ctx.lineWidth = 0.5;
ctx.arcTo(200,30,250,50,20);
ctx.closePath();
ctx.stroke();
</script>
</body>
</html>
繪製貝塞爾曲線
方法:quadraticCurveTo(cp1x,xp1y,x,y)
方法:bezierCurveTo(cp1x,cp1y,cp2x,cp2y,x,y)
這兩個方法分別用於繪製一個控制點和兩個控制點的貝塞爾曲線,畫筆當前點爲曲線的起點,(x,y)爲曲線的終點,(cpx1,cp1y)和(cp2x,cp2y)都是控制點,理解了貝塞爾曲線,這兩個方法就很容易理解:深入理解貝塞爾曲線
實例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<canvas id="c2d">瀏覽器不支持canvas</canvas>
<script>
const canvas = document.querySelector('#c2d');
if(canvas.getContext) {
const ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.moveTo(30,50);
ctx.quadraticCurveTo(40,80,100,50);
ctx.moveTo(130,60);
ctx.bezierCurveTo(160,30,200,100,260,50);
ctx.stroke();
}
</script>
</body>
</html>
組合與剪切
組合與剪切主要是對應多個圖形來說的,組合指的是多個圖形重疊時的組合方式,剪切是指使用路徑來指定繪圖的區域,類似於Photoshop中的蒙版的效果。
組合
圖形的組合是通過globalCompositeOperation屬性來操作的,該屬性可以取下面的值:
- source-over: 後繪製的圖形覆蓋原圖,該值爲默認值
- source-in: 保留後繪製圖形和原圖形重疊的部分,使用後繪製圖形的樣式,其他區域透明,也就是保留相交的部分
- source-out: 保留後繪製圖形不和原圖形重疊的部分,其他區域透明
- source-atop: 保留後繪製圖形和原圖形重疊的部分,使用後繪製圖形的樣式,原圖中的非重疊部分不變
- destination-over: 後繪製圖形被原圖覆蓋,也就是重疊部分顯示原圖
- destination-in: 保留後繪製圖形和原圖形重疊的部分,使用原圖的樣式,其他區域透明
- destination-out: 保留原圖不和後繪製圖形重疊的部分,其他區域透明
- destination-atop: 保留後繪製圖形和原圖形重疊的部分,使用原圖的樣式,後繪製圖形中的非重疊部分不變
- lighter: 後繪製圖形和原圖重疊的部分進行疊加
- copy: 顯示後繪製圖形,不顯示原圖
- xor: 後繪製圖形和原圖重疊的部分進行異或操作
- multiply: 將後繪製圖形和原圖的像素相乘,圖形變暗
- screen: 將後繪製圖形和原圖的像素分別反向後相乘再反向,圖形變亮
- overlay: 組合使用multiply和screen,使亮的部分更亮,暗的部分更暗
- darken: 取兩個圖形中較暗的像素值,例如,#aa0011與#cc3300計算後爲#aa0000
- ighten: 取兩個圖形中較亮的像素值,例如,#aa0011與#cc3300計算後爲#aa3311
- color-dodge: 使用原圖像素除以後繪製圖形的反向像素值
- color-burn: 使用原圖反向像素除以後繪製圖形的像素,然後再反向
- hard-light: 組合使用multiply和screen,它與overlay的區別是將原圖和後繪製圖形進行交換
- soft-light: 類似於hard-light,但比hard-light柔和
- difference: 使用後繪製圖形的像素值減去原圖的像素值
- exclusion: difference操作後降低對比度
- hue: 使用後繪製圖形的色調和原圖的亮度、色度
- saturation: 使用後繪製圖形的色度和原圖的亮度、色調
- color: 使用後繪製圖形的色度、色調和原圖的亮度
- luminosity:使用後繪製圖形的亮度和原圖的色度、色調
示例:
<body>
<canvas id='c2d'>瀏覽器不支持canvas</canvas>
<script>
const canvas = document.getElementById('c2d');
if (canvas.getContext) {
let ctx = canvas.getContext('2d');
ctx.fillStyle = 'red';
ctx.fillRect(30,60,60,40);
ctx.globalCompositeOperation = 'destination-over';
ctx.fillStyle = 'blue';
ctx.fillRect(70,40,60,40);
}
</script>
</body>
剪切
剪切的作用其實是指定新的繪圖區域,如果將圖像繪製到剪切區域外面就顯示不出來了,但是剪切操作不會影響剪切之前的圖形。剪切使用的是clip方法,如下:
- clip([fillRule="nonzero"])
- clip(path[,fillRule="nonzero"])
fillRule:用來指定用你什麼算法來判斷一個點是否在被剪切的區域內,可取“nonzero”或“evenodd”
當路徑是使用beginPath創建時,使用第一種方式直接調用clip,當路徑是使用Path2D創建時,需要使用第二種方式將創建的路徑作爲參數傳入。
示例:
<body>
<canvas id='c2d'>瀏覽器不支持canvas</canvas>
<script>
const canvas = document.getElementById('c2d');
if (canvas.getContext) {
let ctx = canvas.getContext('2d');
ctx.fillRect(110,15,30,45);
ctx.beginPath();
ctx.arc(60,60,45,0,2*Math.PI);
ctx.stroke();
ctx.clip();
ctx.fillRect(0,0,60,60);
}
</script>
</body>
首先畫一個以(110,15)爲左上頂點,寬爲30、高爲45的矩形,接着剪切了一個(60,60)爲圓形、45爲半徑的圓,然後又畫了一個以(0,0)爲左上角,寬和高都是60的矩形。這時第一個矩形可以正常顯示,但是第二個矩形只有剪切區域中的部分(也就是和剪切區域相交的部分)纔可以顯示出來。
座標檢測
座標檢測就是檢測指定的點是否在所畫的路徑中,可以用於動畫和遊戲的碰撞檢測中。座標檢測使用的是isPointInPath方法,方法如下:
- isPointInPath(x,y[,fillRule="nonzero"])
- isPointInPath(path,x,y[,fillRule="nonzero"])
參數中,fillRule也用於指定算法,一般不需要修改;x和y爲要檢測點的座標;path爲使用Path2D新建出來的路徑,如果是beginPath新建的路徑,就可以直接調用。
示例:
<body>
<canvas id='c2d'>瀏覽器不支持canvas</canvas>
<div></div>
<script>
const canvas = document.getElementById('c2d');
if (canvas.getContext) {
let ctx = canvas.getContext('2d');
const newPath = new Path2D();
newPath.rect(30,30,40,60);
const div = document.querySelector('div');
const spanValue = `<span>30,40 is in Path: ${ctx.isPointInPath(newPath,30,40)}</span>`;
const spanValue1 = `<span>20,40 is in Path: ${ctx.isPointInPath(newPath,20,40)}</span>`;
div.innerHTML = spanValue + '<br>' + spanValue1;
}
</script>
</body>
顏色和樣式是通過strokeStyle和fillStyle兩個屬性修改的,它們的默認值都是black,strokeStyle表示畫線(描邊)用的樣式,fillStyle表示填充用的樣式,它們可以被賦予三種類型的值:純色、漸變和模式。
純色
純色有以下三種賦值方法:
- 直接賦予顏色值,包括賦予十六進制和顏色的單詞,例如#323232、red等
- 使用rgb函數賦值,rgb函數有三個十進制(0~255)的參數,分別表示紅、綠、藍的值
- 使用rgba函數賦值,rgba函數在rgb函數的基礎上添加了透明度(alpha),它用第四個參數表示透明度。透明度的取值範圍爲【0,1】,其中,0表示完全透明,1表示完全不透明。
示例:
<body>
<canvas id='c2d'>瀏覽器不支持canvas</canvas>
<script>
const canvas = document.getElementById('c2d');
if (canvas.getContext) {
let ctx = canvas.getContext('2d');
ctx.fillStyle = "blue";
ctx.beginPath();
ctx.rect(0,0,20,20);
ctx.fill();
ctx.fillStyle = "rgb(249,27,27)";
ctx.beginPath();
ctx.rect(20,20,20,20);
ctx.fill();
ctx.fillStyle = "rgb(249,27,27, 0.5)";
ctx.beginPath();
ctx.rect(40,40,20,20);
ctx.fill();
}
</script>
</body>
漸變
漸變的顏色是通過CanvasGradient對象來表示的,它可以使用下面兩個方法來創建:
- createLinearGradient(x0,y0,x1,y1): 創建線性漸變
- createRadialGradient(x0,y0,x1,y1,r1): 創建徑向漸變,也就是散漸變
CanvasGradient對象包含一個addColorStop方法,用來添加漸變的顏色控制點,語法如下:
addColorStop(offset,color)
offset用於設置控制點,取值範圍【0,1】;color用於設置控制點的顏色。
示例:
<body>
<canvas id='c2d'>瀏覽器不支持canvas</canvas>
<script>
const canvas = document.getElementById('c2d');
if (canvas.getContext) {
let ctx = canvas.getContext('2d');
let lineGradient = ctx.createLinearGradient(20,20,100,150);
lineGradient.addColorStop(0, 'red');
lineGradient.addColorStop(0.5, 'rgba(255,255,0,0.7)');
lineGradient.addColorStop(1, '#ff6d00');
ctx.fillStyle = lineGradient;
ctx.beginPath();
ctx.arc(50,50,30,0,2*Math.PI);
ctx.fill();
let radiaGradient = ctx.createRadialGradient(130,50,10,130,50,30);
radiaGradient.addColorStop(0,'rgba(255,204,205,0.3)');
radiaGradient.addColorStop(0.5,'#ffff00');
radiaGradient.addColorStop(1,'#ff6d00');
ctx.fillStyle = radiaGradient;
ctx.fillRect(100,20,60,60);
}
</script>
</body>
模式
模式使用CanvasPattern對象來表示的,它使用createPattern方法來創建,語法如下:
createPattern(image,repetition);
參數中,image爲CanvasImageSource類型,它可以是html中的img節點、video節點、canvas節點或者CanvasRenderingContext2D對象。repetion爲重複方式,它可以取下面4個值:
- repeat: 水平和豎直兩個方向重複
- repeat-x: 水平重複
- repeat-y: 豎直重複
- no-repeat: 不重複
模式的用法就好像使用圖片作爲畫筆繪圖,其中repetition屬性跟css中的background-repeat屬性類似。
示例:
<body>
<canvas id='c2d'>瀏覽器不支持canvas</canvas>
<script>
const canvas = document.getElementById('c2d');
if (canvas.getContext) {
let ctx = canvas.getContext('2d');
var img = new Image();
img.src = 'https://mdn.mozillademos.org/files/222/Canvas_createpattern.png';
img.onload = function () {
var pattern = ctx.createPattern(img, 'repeat');
ctx.fillStyle = pattern;
ctx.fillRect(0, 0, 400, 400);
};
}
</script>
</body>
插入文本
在繪圖的過程中經常需要插入一些文本內容,在CanvasRenderingContext2D中可以使用下面的方法來插入:
- fillText(text,x,y[,maxWidth]):實心文本
- strokeText(text,x,y[,maxWidth]):空心wenb
相關屬性: - font: 字體
- textAlign:排列方式,可選值[start, end, left, right, center]
- direction: 文本方向
- textBaseline: 文本的基線,漢字用不到,值爲top,hanging,middle,alphabetic,ideographic,bottom.
實例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<canvas id="c2d">瀏覽器不支持canvas</canvas>
<script>
const canvas = document.querySelector('#c2d');
if(canvas.getContext) {
const ctx = canvas.getContext('2d');
ctx.font='28px 行楷';
ctx.fillText('愛我中華', 10, 50);
ctx.font = '38px 宋體';
ctx.strokeText('中國加油', 10, 100);
}
</script>
</body>
</html>
插入圖片
在CanvasRenderingContext2D中可以插入圖片,使用drawImage方法,有以下三種調用方式:
- drawImage(image, x, y)
指定圖片繪製位置的左上角 - drawImage(image,x,y,width,height)
指定繪製後的寬和高,這個方法可能會產生變形 - drawImage(image,sx,sy,sWidth,sHeight,dx,dy,dWidth,dHeight)
可以截取原圖的一部分繪製到當前canvas中,並且可以進行縮放,它的後8個參數中的前4個表示在原圖中要截取得位置,sx,sy爲截取的左上角的位置,sWidth和sHeight爲截取的寬度和高度,後4個參數表示在當前canvas中繪製的位置,dx,dy爲繪製的左上角,dWidth和dHeight爲繪製的寬度和高度。
參數中,image爲CanvasImageSource類型,可以是html中的img節點、video節點、canvas節點或者Canvas'RenderingContext2D對象。
實例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<canvas id="c2d" width="800" height="800">瀏覽器不支持canvas</canvas>
<img id="pic" src="./img/Pic2.png" hidden="true">
<script>
window.onload = function () {
const canvas = document.querySelector('#c2d');
if (canvas.getContext) {
const ctx = canvas.getContext('2d');
const pic = document.getElementById('pic');
ctx.drawImage(pic, 0, 0, 100, 100);
ctx.drawImage(pic, 50, 50, 100, 100);
ctx.drawImage(pic, 100, 100, 100, 100);
}
}
</script>
</body>
</html>
環境的保存和恢復
在繪圖的過程中經常需要對環境進行設置,例如填充樣式、描邊,在操作完之後,往往需要恢復到原來的環境,CanvasRenderingContext2D中可以使用save和restore方法快速操作。
環境的保存和恢復還可以進行多層嵌套。多次使用save方法可以創建多個保存點,每次調用restore方法都會按save相反的順序獲取所保存的環境。
實例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<canvas id="c2d" width="600" height="600">瀏覽器不支持canvas</canvas>
<script>
const canvas = document.querySelector('#c2d');
if(canvas.getContext) {
const ctx = canvas.getContext('2d');
ctx.save();
ctx.fillStyle = 'red';
ctx.fillRect(0,0,100,100);
ctx.restore();
ctx.fillRect(100,100,100,100);
}
</script>
</body>
</html>
移動座標原點
方法:translate(x,y):x,y代表移動後x,y座標
旋轉座標系
方法:rotate(angle), 旋轉角度,整數爲逆時針,負數爲順時針。
實例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<canvas id="c2d" width="500" height="500">不支持canvas</canvas>
<script>
const canvas = document.querySelector('#c2d');
if(canvas.getContext) {
const ctx = canvas.getContext('2d');
ctx.fillRect(0,0,10,30);
ctx.translate(10,30);
ctx.fillRect(0,0,10,30);
ctx.translate(10,30);
ctx.rotate(-Math.PI * 1/2);
ctx.fillStyle='red';
ctx.fillRect(0,0,10,30);
}
</script>
</body>
</html>
縮放
方法: scale(x, y)
座標系除了可以移動和旋轉外還可以進行縮放,縮放使用的是scale方法,它有兩個參數,分別標識橫軸和縱軸縮放的比例, 1爲原始大小,大於1爲放大,小於1爲縮小。
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<canvas id="c2d" height="600" width="600">瀏覽器不支持canvas</canvas>
<script>
const canvas = document.querySelector('#c2d');
if(canvas.getContext) {
const ctx = canvas.getContext('2d');
ctx.fillText('愛我中華', 10, 50);
ctx.scale(2,2);
ctx.translate(50,50);
ctx.fillText('愛我中華', 10, 50);
}
</script>
</body>
</html>
同樣是填充一個文本,由於第二次填充文字時,x軸和y軸都同比增加了2倍,所以文字的大小也相應的增加。
陰影
屬性值:
- shadowOffsetX: 陰影的水平偏移距離
- shadowOffsetY: 陰影的豎直偏移距離
- shadowBlur: 陰影的模糊效果,數字越大越模糊
- shadowColor: 陰影顏色
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<canvas id="c2d">瀏覽器不支持canvas</canvas>
<script>
const canvas = document.querySelector('#c2d');
if(canvas.getContext) {
const ctx = canvas.getContext('2d');
// 設置陰影效果
ctx.shadowOffsetX = -7;
ctx.shadowOffsetY = 5;
ctx.shadowBlur = 3;
ctx.shadowColor = 'rgba(255,255,0,0.7)';
ctx.fillStyle = 'red';
ctx.fillRect(15,30,130,40);
}
</script>
</body>
</html>