請各位讀者添加一下作者的微信公眾號,以后有新的文章,將在微信公眾號直接推送給各位,非常感謝。
0. 前言
相信各位小伙伴讀了之前的文章,對 Canvas 基礎已經有了一定的認識和了解,但是大家也一定記得我在上一篇文章留了一個小的坑。
就是我沒有告訴大家該如何去繪制圓,之所以沒有說是因為繪制圓實際上是因為 CanvasRenderingContext2D 對象只提供了兩個繪制矩形的方法,并沒有直接提供繪制圓,橢圓等幾何圖形的方法。為了在 Canvas 上繪制更復雜的方法,必須在 Canvas 上啟用路徑,借用路徑來繪制圖形。
那么我們現在就一起來看一看,該如何使用路徑來繪制圓等圖形吧。
------------------我是華麗的分割線----------------------
下一篇文章預告, canvas 的各種圖像特效。
另外,接下來一段時間,小編要享受一下假期,暫時不會給各位讀者老爺更新啦,希望各位老爺耐心等待。
1.使用路徑
在 Canvas 上使用路徑,可按照下面的步驟進行。
- 調用 CanvasRenderingContext2D 對象的 beginPath()方法開始定義路徑。
- 調用CanvasRenderingContext2D 的各種方法添加子路徑。
- 調用CanvasRenderingContext2D 的 closePath 方法關閉路徑。
- 調用CanvasRenderingContext2D 的fill()或 stroke()方法來填充路徑或者繪制路徑邊框。
那我們明確了該如何去進行應該怎么去使用路徑,那么我們接下來就來介紹一下 canvas 中添加子路徑的方法。
- | - |
---|---|
arc(float x,float y,float radius,float startAngle,float endAngle,boolean counterclockwise) | 向 canvas 的當前路徑上添加一段弧。繪制以 x , y 為圓心,radius 為半徑,從 startAngle 角度開始,到 endAngle 角度結束的圓弧。startAngle 和 endAngle 以角度為單位。 |
arcTo(float x1,float x2,float y1,float y2,float radius) | 向 canvas 的當前路徑上添加一段弧。與上一個方法不同的地方只是定義弧的方式不同。 |
bezierCurveTo(float cpX1, float cpY1, float cpX2, float cpY2, float x, float y) | 在當前路徑上添加一段貝塞爾曲線 |
quadraticCurveTo(float cpX, float cpY,float x,float y) | 向 canvas 當前路徑添加一段二次貝塞爾曲線 |
rect(float x, float y,float width, float height) | 向 canvas 的當前路徑上添加一個矩形 |
方法就這些,但是參數就顯得非常多了,咱們來一條條的來看看這些方法的具體使用吧。
1.1 繪制圓
首先我們來學習下如何繪制圓,首先明確,我們應該去使用 arc ( ) 方法,那么我們該如何去使用這個方法呢?
咱們,放“碼”過來。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div>
<h2>繪制圓形</h2>
<canvas id="canvas_1" width="1000" height="500" style="box-shadow: 0px 0px 20px black;">
當前瀏覽器不支持 canvas
</canvas>
</div>
</body>
<script type="text/javascript">
// 獲取 canvas 元素對應的 DOM 對象
var canvas_1 = document.getElementById("canvas_1");
// 獲取在 canvas 上繪圖的 canvasRenderingContent2D 對象
var ctx = canvas_1.getContext("2d");
// 我們多去繪制幾個圓形,使用下 for 循環
for(var i = 0; i < 10 ; i++){
// 開始定義路徑
ctx.beginPath();
// 添加一段圓弧
ctx.arc(i * 25,i * 25,(i + 1) * 8, 0, Math.PI * 2, true);
// 關閉路徑
ctx.closePath();
// 設置填充顏色
ctx.fillStyle = 'rgba(255,0,255,'+ (10 - i) * 0.1 + ')';
// 填充當前路徑
ctx.fill();
}
</script>
</html>
最后實現效果如下:
不知道小伙伴們是否看懂了上面的程序呢?
如果沒看懂也無所謂,咱們就來一起說一說上面內容中的難點。
首先說一下,Math.PI 實際上指代的就是 π,換而言之也就是 180°,那么我們上面使用的角度是 Math.PI * 2,也就是繪制了一個圓形。
之后再說一下 arc(float x,float y,float radius,float startAngle,float endAngle,boolean counterclockwise)
這個方法。
里面一共有 6 個參數,這六個參數實際上對應的是:
- | - |
---|---|
float x | 指定圓弧的圓心的 X 坐標 |
float y | 指定圓弧的圓心的 Y 坐標 |
float radius | 指定圓弧的半徑 |
float startAngle | 設置圓弧的開始角度 |
float endAngle | 設置圓弧的結束角度 |
boolean counterclockwise | 設置是否順時針旋轉 |
這樣不知道大家對我們繪制圓是否清楚明白了呢?
如果有任何疑問請及時留言回復呦。
1.2 繪制圓角矩形
我們之前已經學習過繪制圓形,也學習過繪制矩形,甚至我們也可以通過 lineJoin 去對我們的元素的圓角去進行修改。
但是,固定的東西我們不需要,我們真正需要的是可以自定義,可以根據我們想要的效果能夠隨意訂制的內容。
為了做到這個目的,我們還可以去使用 arcTo 來去繪制一段圓弧。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div>
<h2>繪制圓形</h2>
<canvas id="canvas_1" width="1000" height="500" style="box-shadow: 0px 0px 20px black;">
當前瀏覽器不支持 canvas
</canvas>
</div>
</body>
<script type="text/javascript">
/*
該方法負責繪制圓角矩形
x1 , y2 : 圓角矩形左上角的坐標
width,height:控制圓角矩形的寬度和高度
radius:控制圓角矩形的四個圓角的半徑
*/
function creatRoundRect(ctx, x1, y1, width, height, radius){
// 移動到左上角的開始點
ctx.moveTo(x1 + radius, y1);
// 添加一條連接開始點到右上角的線段
ctx.lineTo(x1 + width - radius, y1);
// 添加右上角的一段圓弧
ctx.arcTo(x1 + width, y1, x1 + width, y1 + radius, radius);
// 添加一條連接到右下角的線段
ctx.lineTo(x1 + width, y1 + height - radius);
// 添加右下角的一段圓弧
ctx.arcTo(x1 + width, y1 + height, x1 + width - radius, y1 + height, radius);
// 添加一條由右下角連接到左下角的線段
ctx.lineTo(x1 + radius, y1 + height);
// 添加左下的圓弧
ctx.arcTo(x1, y1 + height, x1, y1 + height - radius,radius);
// 添加一條由左下角連接到左上角的線段
ctx.lineTo(x1, y1 + radius);
// 添加一段圓弧
ctx.arcTo(x1, y1, x1 + radius, y1, radius);
ctx.closePath();
}
// 獲取 canvas 元素對應的 DOM 對象
var canvas_1 = document.getElementById("canvas_1");
// 獲取在 canvas 上繪圖的 canvasRenderingContent2D 對象
var ctx = canvas_1.getContext("2d");
ctx.lineWidth = 3;
creatRoundRect(ctx, 30, 30, 200, 100, 20);
ctx.stroke();
</script>
</html>
注意,我在這里分別繪制了四條線和四個弧度角,并且讓他們首尾相連,以此來達到繪制矩形框的作用。
其次就是專門去封裝了一個函數,用于繪制圓角矩形,回頭有需要的小伙伴可以直接自行粘貼呦。
1.3 繪制多角形
不知道大家對之前繪制三角形是否還記得?
我們在繪制三角形的時候,主要是去使用 lineTo 和 moveTo 這兩個方法,可是我們在生活中遇到的圖形遠遠不止這么幾種圖形。
那么我們今天就來學習一下如何去繪制多角形。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div>
<h2>繪制多角形</h2>
<canvas id="canvas_1" width="1000" height="500" style="box-shadow: 0px 0px 20px black;">
當前瀏覽器不支持 canvas
</canvas>
</div>
</body>
<script type="text/javascript">
/*
該方法用于繪制多角形
n:該參數通常設置為奇數,控制繪制 N 角星
dx、dy:控制 N 角星的位置
size:控制 N 角星的大小
*/
function creatStar(context, n, dx, dy, size){
// 開始創建路徑
context.beginPath();
var dig = Math.PI / n * 4;
context.moveTo(dx, y + dy);
for(var i = 0; i <= n; i++){
var x = Math.sin(i * dig);
var y = Math.cos(i * dig);
// 繪制從當前點連接到指定點的線條
context.lineTo(x * size + dx, y * size + dy);
}
// 關閉路徑
context.closePath();
}
// 獲取 canvas 元素對應的 DOM 對象
var canvas_1 = document.getElementById("canvas_1");
// 獲取在 canvas 上繪圖的 canvasRenderingContent2D 對象
var ctx = canvas_1.getContext("2d");
// 繪制三角星
creatStar(ctx, 3, 60, 60, 50);
ctx.fillStyle = '#f00';
ctx.fill();
// 繪制五角星
creatStar(ctx, 5, 160, 60, 50);
ctx.fillStyle = '#0f0';
ctx.fill();
// 繪制七角星
creatStar(ctx, 7, 260, 60, 50);
ctx.fillStyle = '#00f';
ctx.fill();
// 繪制九角星
creatStar(ctx, 9, 360, 60, 50);
ctx.fillStyle = '#f0f';
ctx.fill();
</script>
</html>
可以看到我們又去封裝了一個方法,專門用于繪制多角星,當然我們也可以在這個基礎之上去繼續拓展,這些就需要看小伙伴們的發揮啦。
1.4 繪制曲線
還記得我們在一開始的時候我們學習了五個方法,除了現在已經學習的繪制圓和繪制圓角矩形,是不是還有一些奇奇怪怪的方法?
那么我們現在就開始來學習這些方法。
首先先來學習一下,添加貝塞爾曲線。
- | - |
---|---|
bezierCurveTo(float cpX1, float cpY1, float cpX2, float cpY2, float x, float y) | 在當前路徑上添加一段貝塞爾曲線 |
quadraticCurveTo(float cpX, float cpY,float x,float y) | 向 canvas 當前路徑添加一段二次貝塞爾曲線 |
首先來看看第一個方法,第一個方法中實際上有四個點需要注意。
他們分別是
- 左下角的開始點
- 粉紅色的第一個控制點(錨點)
- 藏青色的第二個控制點(錨點)
- 右上角的結束點
而方法中 cpX1 和 cpY1 則是控制第一個控制點的坐標,
后面的 cpX2 和 cpY2 則是控制第二個控制點的坐標。
而二次貝塞爾曲線又是怎么回事呢?
和正常貝塞爾不同,二次曲線只需要三個點:
- 左下角的開始點
- 藏青色的控制點
- 右上角的結束點
方法中的 cpX 和 cpY 則是去設置控制點的坐標。
那么我們來一起試一試,該如何去繪制一個個花朵。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div>
<h2>繪制花朵</h2>
<canvas id="canvas_1" width="1000" height="500" style="box-shadow: 0px 0px 20px black;">
當前瀏覽器不支持 canvas
</canvas>
</div>
</body>
<script type="text/javascript">
/*
該方法負責繪制花朵
n:該參數控制花朵的花瓣數
dx,dy:控制花朵的位置
size:控制花朵的大小
length:控制花瓣的長度
*/
function creatFlower(context, n, dx, dy, size, length){
// 開始創建路徑
context.beginPath();
context.moveTo(dx, dy + size);
var dig = 2 * Math.PI / n;
for(var i = 1; i < n + 1; i++){
// 計算控制點的坐標
var ctrlX = Math.sin((i - 0.5) * dig) * length + dx;
var ctrlY = Math.cos((i - 0.5) * dig) * length + dy;
// 計算結束點的坐標
var x = Math.sin(i * dig) * size + dx;
var y = Math.cos(i * dig) * size + dy;
// 繪制二次曲線
context.quadraticCurveTo(ctrlX, ctrlY, x, y);
}
context.closePath();
}
// 獲取 canvas 元素對應的 DOM 對象
var canvas_1 = document.getElementById("canvas_1");
// 獲取在 canvas 上繪圖的 canvasRenderingContent2D 對象
var ctx = canvas_1.getContext("2d");
// 繪制五瓣的花朵
creatFlower(ctx, 5, 70, 100, 30, 80);
ctx.fillStyle = "#f00";
ctx.fill();
// 繪制六瓣的花朵
creatFlower(ctx, 6, 220, 100, 30, 80);
ctx.fillStyle = "#ff0";
ctx.fill();
// 繪制七瓣的花朵
creatFlower(ctx, 7, 370, 100, 30, 80);
ctx.fillStyle = "#f0f";
ctx.fill();
</script>
</html>
1.5 繪制位圖
一直到現在我們講了如何去繪制線,三角形,多角星,矩形,圓,花朵,圓角矩形等各種圖形。
但是除了這些基礎圖形之外,我們還可以去繪制“位圖”,讓一張圖片繪制在我們的畫布之上。
那我們怎么來做呢?
我們既然想將我們的圖片載入到我們的畫布中,怎么做呢?我們先來差混構建一個 Image 對象。
var image = new Image();
image.src = "lipeng.png";
需要注意兩點,
- 我們的程序只是創建,加載圖片,所以調用 image 時無需傳入寬度和高度,這樣創建的 image 將會與 src 屬性指定的圖片保持相同的寬度和高度。
- src 加載圖片是進行異步加載,如果圖片數據太大,或者直接來自于網絡,當我們網速較慢的時候,會發現我們的圖片繪制會非常慢,導致影響用戶使用。我們可以使用 onload 去保證我們一定是在圖片加載完成后再繪制。
var image = new Image();
image.src = "lipeng.png";
image.onload = function(){
//繪制圖片
}
學習了如何去加載圖片,我們就可以向我們的畫布中添加圖片了么?
沒有方法你怎么去添加圖片呀,魂淡。
我們還要學習添加圖片的方法,這里跟大家說三種方法。
- | - |
---|---|
drawImage(Image image, float x, float y) | 把 image 繪制在 x, y 處。該方法不會對圖片做任何縮放處理,繪制處理的圖片保持原來的大小 |
drawImage(Image image, float x, float y, float width, float height) | 把 image 繪制在 x, y 處。該方法會對圖片進行縮放,繪制出來的寬度為 width,高度為 height。 |
drawImage(Image image, integer sx, integer sy, integer sw, integer sh, float dx, float dy,float dw, float dh) | 該方法將會從 image 上“挖出”一塊繪制到畫布上。其中 sx, sy 兩個參數控制從原圖片上的哪一個位置開始挖去, sw, sh 兩個參數控制從原圖片挖球的寬度和高度;dx, dy 兩個參數控制把挖取的圖片繪制到畫布上的哪個位置,而 dw, dh 則控制對繪制圖片進行縮放,繪制出來的寬度是 dw, 高度 dh |
我們知道了方法,那就來一起學習下,該如何用代碼來實現吧。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div>
<h2>繪制位圖</h2>
<canvas id="canvas_1" width="1000" height="500" style="box-shadow: 0px 0px 20px black;">
當前瀏覽器不支持 canvas
</canvas>
</div>
</body>
<script type="text/javascript">
// 獲取 canvas 元素對應的 DOM 對象
var canvas_1 = document.getElementById("canvas_1");
// 獲取在 canvas 上繪圖的 canvasRenderingContent2D 對象
var ctx = canvas_1.getContext("2d");
// 創建 image 對象
var image = new Image();
// 創建 image 對象裝載圖片
image.src = "lipeng.png";
// 當圖片加載完成后觸發該函數
image.onload = function(){
// 保持原大小繪制圖片
ctx.drawImage(image, 20, 10);
// 繪制圖片的時候進行縮放
ctx.drawImage(image, 600, 10, 76, 110);
// 從原圖中挖去一塊,放大三倍后繪制在 canvas 上
var sd = 50;
var sh = 50;
/*
參數說明
Image image, integer sx, integer sy, integer sw, integer sh, float dx, float dy,float dw, float dh
sx, sy 兩個參數控制從原圖片上的哪一個位置開始挖去,
sw, sh 兩個參數控制從原圖片挖球的寬度和高度;
dx, dy 兩個參數控制把挖取的圖片繪制到畫布上的哪個位置,而
dw, dh 則控制對繪制圖片進行縮放,繪制出來的寬度是 dw, 高度 dh
*/
ctx.drawImage(image, 230, 220,sd, sh, 765, 10, sd * 3, sh * 3);
}
</script>
</html>
結果如下:
怎么樣,是不是覺得瞬間高大上了呢?趕快學起來啦。