canvas--基本用法和绘制

1.canvas元素

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

canvas 标签只有两个属性—— width和height。
由于某些较老的浏览器(尤其是IE9之前的IE浏览器)或者文本浏览器不支持HTML元素”canvas”,在这些浏览器上你应该总是能展示替代内容。

1
2
3
<canvas id="tutorial" width="150" height="150">
你的浏览器不支持canvas元素
</canvas>

2.渲染上下文(The rendering context)

  • canvas 元素创造了一个固定大小的画布,它公开了一个或多个渲染上下文,其可以用来绘制和处理要展示的内容。
  • canvas起初是空白的。为了展示,首先脚本需要找到渲染上下文,然后在它的上面绘制。canvas 元素有一个叫做 getContext() 的方法,这个方法是用来获得渲染上下文和它的绘画功能。
  • getContext()只有一个参数,上下文的格式。
1
2
3
4
5
6
7
var canvas = document.getElementById('tutorial');
if(canvas.getContext){
var ctx = canvas.getContext('2d');
// drawing code here
} else {
// canvas-unsupported code here
}

3.绘制

canvas 只支持两种形式的图形绘制:矩形和路径(由一系列点连成的线段)。所有其他类型的图形都是通过一条或者多条路径组合而成的。

3.1 绘制矩形

canvas提供了三种方法绘制矩形:

1.fillRect(x, y, width, height) 绘制一个填充的矩形
2.strokeRect(x, y, width, height) 绘制一个矩形的边框
3.clearRect(x, y, width, height) 清除指定矩形区域,让清除部分完全透明

参数:

  • x与y指定了在canvas画布上所绘制的矩形的左上角(相对于原点)的坐标。
  • width和height设置矩形的尺寸。

举个栗子

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
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.canvas {
width: 900px;
height: 900px;
margin: 20px auto;
}

canvas {
border: 1px solid #aaa;
margin: 10px;
}
</style>
<script>
function draw() {
var canvas = document.getElementById('tutorial');
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);
}
}
</script>
</head>

<body onload="draw();">
<div class="canvas">
<canvas id="tutorial" width="150" height="150">
你的浏览器不支持canvas
</canvas>
</div>
</body>

</html>

效果如下图:

3.2 绘制路径

图形的基本元素是路径。路径是通过不同颜色和宽度的线段或曲线相连形成的不同形状的点的集合。一个路径,甚至一个子路径,都是闭合的。使用路径绘制图形需要一些额外的步骤。

  • 1.首先,你需要创建路径起始点。
  • 2.然后你使用画图命令去画出路径。
  • 3.之后你把路径封闭。
  • 4.一旦路径生成,你就能通过描边或填充路径区域来渲染图形。

常用方法:

1.beginPath() 新建一条路径,生成之后,图形绘制命令被指向到路径上生成路径
2.closePath() 闭合路径之后图形绘制命令又重新指向到上下文中
3.moveTo(x, y) 将一个新的子路径的起始点移动到(x,y)坐标。
4.lineTo(x, y) 使用直线连接子路径的最后的点到x,y坐标。
5.arc(x, y, r, startAngle, endAngle, anticlockwise)绘制一段圆弧路径
  • 圆弧路径的圆心在 (x, y) 位置
  • 半径为 r
  • 根据anticlockwise (默认为顺时针,false)指定的方向从 startAngle 开始绘制,到 endAngle 结束。
  • 参数anticlockwise为一个布尔值。为true时,是逆时针方向,否则顺时针方向。
  • arc()函数中表示角的单位是弧度,不是角度。角度与弧度的js表达式:
    弧度=(Math.PI/180)*角度
6.stroke() 通过线条来绘制图形轮廓
7.fill() 通过填充路径的内容区域生成实心的图形

绘制三角形:(绘制矩形)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function draw() {
var canvas = document.getElementById('tutorial');
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
ctx.beginPath();
// 注意:当前路径为空,即调用beginPath()之后,或者canvas刚建的时候,第一条路径构造命令通常被视为是moveTo()
// 无论实际上是什么。出于这个原因,你几乎总是要在设置路径之后专门指定你的起始位置。
ctx.moveTo(75,50);
ctx.lineTo(100,75);
ctx.lineTo(100,25);
ctx.fill();
// 当你调用fill()函数时,所有没有闭合的形状都会自动闭合,所以你不需要调用closePath()函数。但是调用stroke()时不会自动闭合。
}
}

效果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function draw() {
var canvas = document.getElementById('tutorial');
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
ctx.beginPath();
// 注意:当前路径为空,即调用beginPath()之后,或者canvas刚建的时候,第一条路径构造命令通常被视为是moveTo()
// 无论实际上是什么。出于这个原因,你几乎总是要在设置路径之后专门指定你的起始位置。
ctx.moveTo(75,50);
ctx.lineTo(100,75);
ctx.lineTo(100,25);
ctx.stroke();
// 当你调用fill()函数时,所有没有闭合的形状都会自动闭合,所以你不需要调用closePath()函数。但是调用stroke()时不会自动闭合。
}
}

效果如下:

绘制笑脸:(绘制路径)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function draw() {
var canvas = document.getElementById('tutorial');
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.arc(75,75,50,0,Math.PI*2,true); // 圆心(75,75) 半径50 起始角度0,结束角度360
ctx.moveTo(110,75);
ctx.arc(75,75,35,0,Math.PI,false); // 圆心(75,75) 半径35 起始角度0,结束角度180
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();
}
}

效果如下:

stroke与fill的区别

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function draw() {
var canvas = document.getElementById('tutorial');
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.moveTo(25,25);
ctx.lineTo(125,25);
ctx.lineTo(25,125);
ctx.fill();

ctx.beginPath();
ctx.moveTo(125,125);
ctx.lineTo(125,45);
ctx.lineTo(45,125);
// 因为路径使用填充(fill)时,路径自动闭合,使用描边(stroke)则不会闭合路径。
// 如果没有添加闭合路径closePath()到描述三角形函数中,则只绘制了两条线段,并不是一个完整的三角形。
ctx.closePath();
ctx.stroke();
}
}

效果如下:

更复杂的绘制路径的方法

8.quadraticCurveTo(cp1x, cp1y, x, y) 绘制二次贝塞尔曲线,cp1x,cp1y为一个控制点,x,y为结束点。
9.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)绘制三次贝塞尔曲线,cp1x,cp1y为控制点一,cp2x,cp2y为控制点二,x,y为结束点。

二次贝塞尔曲线绘制会话气泡

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function draw() {
var canvas = document.getElementById('tutorial');
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,60,100);
ctx.quadraticCurveTo(125,100,125,62.5);
ctx.quadraticCurveTo(125,25,75,25);
ctx.stroke();
}
}

效果如图:

三次贝塞尔曲线绘制爱心

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function draw() {
var canvas = document.getElementById('tutorial');
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.stroke();
ctx.fill();
}
}

效果如下: