Canvas (1) 繪製圓形、三角形、直線

Canvas 元素

一個基本的 canvas 元素看起來類似 img ,但是沒有 srcalt 屬性,而且 元素必須要有結束標籤。只有 widthheight兩個屬性,如果沒有指定,預設值是寬 300px 高 150px,但也可以透過 CSS 設定。沒有套用樣式規定時,會被初始成全透明。

1
<canvas id="canvas" width="150" height="150"></canvas>

要在 canvas 上進行繪製渲染的初始化,只要 2 個步驟,首先要取得 canvas 元素,再使用 getContext() 取得渲染環境,getContext()輸入參數只有渲染環境類型一項。除了在 HTML 標籤或 CSS 裡設定寬高,也可以在程式腳本裡設定。

1
2
3
4
var canvas = document.getElementById("canvas");
canvas.width = 1024;
canvas.height = 1024;
var context = canvas.getContext("2d");

簡單的兼容性檢查

藉由檢查 getContext()方法是否存在,來測試瀏覽器兼容。

1
2
3
4
5
6
7
8
9
10
var canvas = document.getElementById("canvas");

if (canvas.getContext) {
var context = canvas.getContext("2d");
} else {
alert("瀏覽器不支援 Canvas,請更換瀏覽器再試");
}

canvas.width = 1024;
canvas.height = 1024;

畫出直線、多邊型、七巧板

上面的上下文環境裡面已經得到一個 1024 x 1024 像素的畫布。要在上面繪製圖形,必須使用座標空間。在座標空間上繪圖,一個網格等於 1px,網格的座標原點(0,0) 從左上角開始。像是下圖,藍色方塊的位置為從左往右推 x pixels、從上往下推 y pixels (亦即座標 (x, y) ),所有元素定位都相對於此左上角圓點。

接下來要練習繪製直線,底下是畫出一條直線的方式,以白話來說就是把筆尖狀態先設定落在座標 (100, 100) 的啟始點,並且移動到座標 (300, 300) 的位置,並調用 stroke() 方法繪製。

1
2
3
4
5
6
7
8
9
10
//狀態設置
context.moveTo(100, 100);
context.lineTo(300, 300);

//線條寬度
ctx.lineWidth = 5;
//線條樣式,顏色代碼必須設置為字串
ctx.strokeStyle = "red";
//繪圖指令
context.stroke();

描繪出一個直角三角形

1
2
3
4
5
ctx.moveTo(100, 100);
ctx.lineTo(400, 400);
ctx.lineTo(100, 400);
ctx.lineTo(100, 100);
context.stroke();

要畫出一個填滿顏色的圖案,要改用 fill() 填滿路徑內容產生圖案

1
2
3
4
5
ctx.moveTo(100, 100);
ctx.lineTo(400, 400);
ctx.lineTo(100, 400);
ctx.lineTo(100, 100);
context.fill();

如果要用多個路徑繪製 2 組不同的圖形,因為調用 stroke() 的特性,一開始要先產生路徑,然後用繪圖指令畫出路徑,然後再結束路徑。
先看看沒有使用產生與結束路徑方法的結果。 底下本來要畫出 2 組圖形,結果沒有個別指定產生與結束路徑,所以第二個 stroke() 的運作改變了第一個 stroke() 的繪製結果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//畫出三角形
ctx.moveTo(100, 100);
ctx.lineTo(400, 400);
ctx.lineTo(100, 400);
ctx.lineTo(100, 100);

ctx.lineWidth = 5;
ctx.strokeStyle = "red";
ctx.stroke();

//畫出直線
ctx.moveTo(150, 150);
ctx.lineTo(400, 300);
ctx.strokeStyle = "black";
ctx.stroke();

正確的繪製方法像這樣,要產生路徑並關閉路徑。因為 canvas 繪製圖形使用的指定涉及狀態的改變。

1
2
3
4
5
6
7
8
9
10
11
//畫出三角形
ctx.beginPath(); //產生一個新路徑,產生後再使用繪圖指令來設定路徑。
ctx.moveTo(100, 100);
ctx.lineTo(400, 400);
ctx.lineTo(100, 400);
ctx.lineTo(100, 100);
ctx.closePath(); //閉合路徑好讓新的繪圖指令來設定路徑。

ctx.lineWidth = 5;
ctx.strokeStyle = "red";
ctx.stroke();

接下來嘗試繪製出一個七巧板,先設定一個陣列,裡面有七個物件,物件內各包含區塊的幾個頂點座標與顏色屬性。
再用迴圈遍歷這個陣列,每遍歷一次就調用一個 draw() 函數, 函數傳入七巧板中的 1 塊,與繪圖環境上下文這兩個參數。接下來依序開啟路徑、把起始座標移動到七巧板的頂點的第一個座標位置,再使用迴圈順次使用 lineTo() 方法繪製後續的座標。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
var tangram = [
{
p: [
{
x: 0,
y: 0
},
{
x: 800,
y: 0
},
{
x: 400,
y: 400
}
],
color: "#caff67"
},
{
p: [
{
x: 0,
y: 0
},
{
x: 400,
y: 400
},
{
x: 400,
y: 800
}
],
color: "#67becf"
},
{
p: [
{
x: 800,
y: 0
},
{
x: 800,
y: 400
},
{
x: 600,
y: 600
},
{
x: 600,
y: 200
}
],
color: "#ef3d61"
},
{
p: [
{
x: 600,
y: 200
},
{
x: 600,
y: 600
},
{
x: 400,
y: 400
}
],
color: "#f9f51a"
},
{
p: [
{
x: 400,
y: 400
},
{
x: 600,
y: 600
},
{
x: 400,
y: 800
},
{
x: 200,
y: 600
}
],
color: "#a594c0"
},
{
p: [
{
x: 200,
y: 600
},
{
x: 400,
y: 800
},
{
x: 000,
y: 800
}
],
color: "#fa8ecc"
},
{
p: [
{
x: 800,
y: 400
},
{
x: 800,
y: 800
},
{
x: 400,
y: 800
}
],
color: "#f6ca29"
}
];

window.onload = function() {
var canvas = document.getElementById("canvas");
canvas.width = 800;
canvas.height = 800;
var cxt = canvas.getContext("2d");
for (var i = 0; i < this.tangram.length; i++) {
draw(tangram[i], cxt);
}
};

function draw(piece, cxt) {
cxt.beginPath();
cxt.moveTo(piece.p[0].x, piece.p[0].y);
for (var i = 1; i < piece.p.length; i++) {
cxt.lineTo(piece.p[i].x, piece.p[i].y);
}
cxt.closePath();
cxt.fillStyle = piece.color;
cxt.fill();
}

畫出圓形和弧形

arc()方法可以畫出一個弧形,接受五個參數: x, y 代表圓心座標點,radius 代表半徑,startAngle, endAngle 分別代表沿著弧形曲線上的起始點與結束點的弧度,弧度測量是相對於 x 軸,anticlockwise 為 true 代表逆時針作圖、false 代表順時針作圖。

1
arc(x, y, radius, startAngle, endAngle, anticlockwise);

繪製一個圓形的初始化座標是下圖 x 軸的右側為啟始點。

底下是從座標 (300,300) 開始,半徑 200,由圓弧啟始點畫 1.5 個 PI 的圓形

1
2
3
4
5
6
7
8
9
10
window.onload = function() {
var canvas = document.getElementById("canvas");
canvas.width = 1024;
canvas.height = 768;
var cxt = canvas.getContext("2d");
cxt.lineWidth = 5;
cxt.strokeStyle = "black";
cxt.arc(300, 300, 200, 0, 1.5 * Math.PI);
cxt.stroke();
};

以下依序畫出 2 組弧形,2 組的差別在有指定跟沒指定封閉路徑

1
2
3
4
5
6
7
8
9
10
11
12
13
for (var i = 0; i < 10; i++) {
cxt.beginPath();
cxt.arc(50 + i * 100, 60, 40, 0, (2 * Math.PI * (i + 1)) / 10);
cxt.closePath();
cxt.stroke();
}

for (var i = 0; i < 10; i++) {
cxt.beginPath();
cxt.arc(50 + i * 100, 180, 40, 0, (2 * Math.PI * (i + 1)) / 10);

cxt.stroke();
}

填充顏色

要設定圖形的顏色,我們有兩個屬性能用: fillStyle 與 storkeStyle.

1
2
3
4
5
cxt.beginPath();
cxt.arc(200, 200, 100, 0, 2 * this.Math.PI);
cxt.closePath();
cxt.fillStyle = "#636766"; //設定填滿圖形時用的顏色.
cxt.fill();

漸層色

使用 createRadialGradient(x1, y1, r1, x2, y2, r2) 產生一個放射狀漸層物件,第一個圓圓心落在(x1, y1)、半徑為 r1,第二個圓之圓心落在(x2, y2)、半徑為 r2。

gradient.addColorStop(position, color)方法可以添加顏色上去。color 是顏色的字串表示,而 position 介於 0.0 到 1.0 之間,定義了該顏色在漸層中的相對位置。

1
2
3
4
5
var gradient = cxt.createRadialGradient(200, 200, 50, 200, 200, 20);
gradient.addColorStop(0, "#0a0a0a");
gradient.addColorStop(1, "#636766");
cxt.fillStyle = gradient;
cxt.fill();

Powered by Hexo and Hexo-theme-hiker

Copyright © 2013 - 2020 CYC'S BLOG All Rights Reserved.

UV : | PV :