文中例子來源:https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API/Tutorial/Drawing_shapes,在這裏表示感謝。
由於Web課程的Demo想做iPone的購買界面,原因是我覺得蘋果的設計實在漂亮。就去學習,有用到Canvas標籤,這個蘋果引領起來的標籤實在強大。學習記錄在此。
用法
<canvas>
標籤的用法是在<body>
中放好位置,然後在js中進行配置。簡單的Demo代碼如下,忘記了看到可以儘快上手:
<head>
<meta charset="UTF-8">
<title>CanvasTest</title>
<script type="text/javascript">
function draw() {
var canvas = document.getElementById("canvas");
if(canvas.getContext)
{
var ctx = canvas.getContext("2d");
ctx.fillStyle = "rgb(200, 0, 0)"; //顏色
ctx.fillRect(10, 10, 55, 50); //位置和大小
ctx.fillStyle = "rgba(0, 0, 200, 0.5)"; //顏色,透明度
ctx.fillRect (30, 30, 55, 50); //位置和大小
}
}
</script>
<style type="text/css">
canvas {
border: 1px solid black;
}
</style>
</head>
<body onload="draw()">
<canvas id="canvas" width="150" height="150">
//這裏存放替代內容,可以用文本與圖片
</canvas>
</body>
矩形繪製
矩形繪製有三種常用方法
fillRect(x, y, width, height) //繪製一個填充的矩形
strokeRect(x, y, width, height) //繪製一個矩形的邊框
clearRect(x, y, width, height) //清除指定矩形區域,讓清除部分完全透明。
繪製例子:
function draw() {
var canvas = document.getElementById('canvas');
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
ctx.fillRect(25,25,100,100);
ctx.clearRect(45,45,60,60);
ctx.strokeRect(50,50,50,50);
}
}
另外還可以用react()
函數繪製矩形。
rect(x, y, width, height) //繪製一個左上角座標爲(x,y),寬高爲width以及height的矩形。
當該方法執行的時候,moveTo()方法自動設置座標參數(0,0)。也就是說,當前筆觸自動重置會默認座標。
繪製路徑
非基本的圖形可以由路徑繪製。繪製路徑是圖形繪製裏的一個基本內容。通俗的講就是爲想畫的圖形畫邊界。
用路徑繪製圖形步驟如下:
- 首先,你需要創建路徑起始點。
- 然後你使用畫圖命令去畫出路徑。
- 之後你把路徑封閉。
- 一旦路徑生成,你就能通過描邊或填充路徑區域來渲染圖形。
接下來是繪製圖形所用到的函數:
beginPath() //新建一條路徑,生成之後,圖形繪製命令被指向到路徑上生成路徑。(相當於 文件-新建)
closePath() //閉合路徑之後圖形繪製命令又重新指向到上下文中。
stroke() //通過線條來繪製圖形輪廓。
fill() //通過填充路徑的內容區域生成實心的圖形。填充時會自動閉合。
用路徑繪製一個三角形的例子:
function draw() {
var canvas = document.getElementById('canvas');
if (canvas.getContext){
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.moveTo(75,50);
ctx.lineTo(100,75);
ctx.lineTo(100,25);
ctx.fill();
}
}
其中moveTo()
函數是一個移動筆觸,用來將筆觸移動到指定座標上,十分有用。
而lineTo
是繪製直線的函數,繪製一條到座標位置的直線。
下面是一個靈活運用移動筆觸繪製笑臉的例子:
function draw() {
var canvas = document.getElementById('canvas');
if (canvas.getContext){
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.arc(75,75,50,0,Math.PI*2,true); // 繪製
ctx.moveTo(110,75);
ctx.arc(75,75,35,0,Math.PI,false); // 口(順時針)
ctx.moveTo(65,65);
ctx.arc(60,65,5,0,Math.PI*2,true); // 左眼
ctx.moveTo(95,65);
ctx.arc(90,65,5,0,Math.PI*2,true); // 右眼
ctx.stroke();
}
}
例子中的arc()
方法用來繪製弧線。使用方法如下:
arc(x, y, radius, startAngle, endAngle, anticlockwise) //畫一個以(x,y)爲圓心的以radius爲半徑的圓弧(圓),從startAngle開始到endAngle結束,按照anticlockwise給定的方向(默認爲順時針)來生成。
arcTo(x1, y1, x2, y2, radius) //根據給定的控制點和半徑畫一段圓弧,再以直線連接兩個控制點(這個方法不推薦使用)。
arc()
函數六個函數分別爲:橫縱座標、半徑、始末弧度、旋轉方向(正逆否順)
需要注意的是arc指的是弧度而不是角度,計算公式:radians=(Math.PI/180)*degrees
下面是12個不同角度與填充圓弧的例子:
function draw() {
var canvas = document.getElementById('canvas');
if (canvas.getContext){
var ctx = canvas.getContext('2d');
for(var i=0;i<4;i++){
for(var j=0;j<3;j++){
ctx.beginPath();
var x = 25+j*50; // x 座標值
var y = 25+i*50; // y 座標值
var radius = 20; // 圓弧半徑
var startAngle = 0; // 開始點
var endAngle = Math.PI+(Math.PI*j)/2; // 結束點
var anticlockwise = i%2==0 ? false : true; // 順時針或逆時針
ctx.arc(x, y, radius, startAngle, endAngle, anticlockwise);
if (i>1){
ctx.fill();
} else {
ctx.stroke();
}
}
}
}
}
貝塞爾曲線
貝塞爾曲線用來繪製複雜有規律的圖形,具體圖像參考維基百科:https://zh.wikipedia.org/wiki/%E8%B2%9D%E8%8C%B2%E6%9B%B2%E7%B7%9A。
貝塞爾曲線的使用函數:
quadraticCurveTo(cp1x, cp1y, x, y) //繪製二次貝塞爾曲線,cp1x,cp1y爲一個控制點,x,y爲結束點。
bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) //繪製三次貝塞爾曲線,cp1x,cp1y爲控制點一,cp2x,cp2y爲控制點二,x,y爲結束點。
上圖是兩種貝塞爾曲線的圖示。在圖中,藍點爲起始點,結束點(x, y),控制點(cpx, cpy)。
二次貝塞爾曲線
這個例子使用多個貝塞爾曲線來渲染對話氣泡。
function draw() {
var canvas = document.getElementById('canvas');
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
// 二次貝爾賽曲線
ctx.beginPath();
ctx.moveTo(75,25);
ctx.quadraticCurveTo(25,25,25,62.5);
ctx.quadraticCurveTo(25,100,50,100);
ctx.quadraticCurveTo(50,120,30,125);
ctx.quadraticCurveTo(60,120,65,100);
ctx.quadraticCurveTo(125,100,125,62.5);
ctx.quadraticCurveTo(125,25,75,25);
ctx.stroke();
}
}
三次貝塞爾曲線
這個例子使用貝塞爾曲線繪製心形。
function draw() {
var canvas = document.getElementById('canvas');
if (canvas.getContext){
var ctx = canvas.getContext('2d');
//三次貝塞爾曲線
ctx.beginPath();
ctx.moveTo(75,40);
ctx.bezierCurveTo(75,37,70,25,50,25);
ctx.bezierCurveTo(20,25,20,62.5,20,62.5);
ctx.bezierCurveTo(20,80,40,102,75,120);
ctx.bezierCurveTo(110,102,130,80,130,62.5);
ctx.bezierCurveTo(130,62.5,130,25,100,25);
ctx.bezierCurveTo(85,25,75,37,75,40);
ctx.fill();
}
}
(根據向同學請教的經驗:貝塞爾曲線是用來畫曲線的,如果你想自己畫哪種曲線的畫,可以把起點終點確定,控制點靠試)
組合使用
這個是MDN上組合使用的例子,教程說實際上很簡單,你們隨意感受下……
function draw() {
var canvas = document.getElementById('canvas');
if (canvas.getContext){
var ctx = canvas.getContext('2d');
roundedRect(ctx,12,12,150,150,15);
roundedRect(ctx,19,19,150,150,9);
roundedRect(ctx,53,53,49,33,10);
roundedRect(ctx,53,119,49,16,6);
roundedRect(ctx,135,53,49,33,10);
roundedRect(ctx,135,119,25,49,10);
ctx.beginPath();
ctx.arc(37,37,13,Math.PI/7,-Math.PI/7,false);
ctx.lineTo(31,37);
ctx.fill();
for(var i=0;i<8;i++){
ctx.fillRect(51+i*16,35,4,4);
}
for(i=0;i<6;i++){
ctx.fillRect(115,51+i*16,4,4);
}
for(i=0;i<8;i++){
ctx.fillRect(51+i*16,99,4,4);
}
ctx.beginPath();
ctx.moveTo(83,116);
ctx.lineTo(83,102);
ctx.bezierCurveTo(83,94,89,88,97,88);
ctx.bezierCurveTo(105,88,111,94,111,102);
ctx.lineTo(111,116);
ctx.lineTo(106.333,111.333);
ctx.lineTo(101.666,116);
ctx.lineTo(97,111.333);
ctx.lineTo(92.333,116);
ctx.lineTo(87.666,111.333);
ctx.lineTo(83,116);
ctx.fill();
ctx.fillStyle = "white";
ctx.beginPath();
ctx.moveTo(91,96);
ctx.bezierCurveTo(88,96,87,99,87,101);
ctx.bezierCurveTo(87,103,88,106,91,106);
ctx.bezierCurveTo(94,106,95,103,95,101);
ctx.bezierCurveTo(95,99,94,96,91,96);
ctx.moveTo(103,96);
ctx.bezierCurveTo(100,96,99,99,99,101);
ctx.bezierCurveTo(99,103,100,106,103,106);
ctx.bezierCurveTo(106,106,107,103,107,101);
ctx.bezierCurveTo(107,99,106,96,103,96);
ctx.fill();
ctx.fillStyle = "black";
ctx.beginPath();
ctx.arc(101,102,2,0,Math.PI*2,true);
ctx.fill();
ctx.beginPath();
ctx.arc(89,102,2,0,Math.PI*2,true);
ctx.fill();
}
}
// 封裝的一個用於繪製圓角矩形的函數.
function roundedRect(ctx,x,y,width,height,radius){
ctx.beginPath();
ctx.moveTo(x,y+radius);
ctx.lineTo(x,y+height-radius);
ctx.quadraticCurveTo(x,y+height,x+radius,y+height);
ctx.lineTo(x+width-radius,y+height);
ctx.quadraticCurveTo(x+width,y+height,x+width,y+height-radius);
ctx.lineTo(x+width,y+radius);
ctx.quadraticCurveTo(x+width,y,x+width-radius,y);
ctx.lineTo(x+radius,y);
ctx.quadraticCurveTo(x,y,x,y+radius);
ctx.stroke();
}
Path2D 對象
Path2D對象用於記錄圖像,使圖像成爲一個對象,方便之後使用。之前的路徑方法都可以在Path2D中使用。
new Path2D(); // 空的Path對象
new Path2D(path); // 克隆Path對象
new Path2D(d); // 從SVG建立Path對象
下面是一個Path2D的使用例子:
function draw() {
var canvas = document.getElementById('canvas');
if (canvas.getContext){
var ctx = canvas.getContext('2d');
var rectangle = new Path2D();
rectangle.rect(10, 10, 50, 50);
var circle = new Path2D();
circle.moveTo(125, 35);
circle.arc(100, 35, 25, 0, 2 * Math.PI);
ctx.stroke(rectangle);
ctx.fill(circle);
}
}
SVG(Scalable Vector Graphics) path
可伸縮向量圖形(Scalable Vector Graphics)是另外一種繪製的方法,操作方法爲定點(Mx y)——水平移動(h x)——下移(v x)——左移(h x)——回到原點(z)。這將存儲爲一個SVG data path 供Path2D使用。例子如下:
var p = new Path2D("M10 10 h 80 v 80 h -80 Z");