Canvas 基础用法
作者: dkvirus 发表于: 2018-09-02 10:01:41 最近更新: 2018-09-11 21:19:02

一、概述

1. 介绍

用 js 在 html 中绘画。

2. 画布与画笔

<canvas> 标签具有行内标签在一行展示的特性,也有块级元素设置宽度和高度的特性。

1
2
3
4
5
6
7
8
9
10
11
12
// 准备画布,宽 500,高 500
<canvas id="myCanvas" width="500" height="500">浏览器不支持canvas</canvas>
<script>
function draw () {
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d'); // 画笔

// ... draw anything ...
}

draw();
</script>

3. 路径

在画人物素描时,会先用铅笔描出人物轮廓,这个轮廓在 canvas 里就是 路径。有了轮廓之后,可以选择把轮廓描实(stroke),如果轮廓是封闭曲线,还可以进行颜色填充(fill)。

关于路径的几个 api 如下:

方法 说明
begnPath() 告诉 canvas,准备画轮廓了
moveTo(x, y) 画笔第一个点放在什么位置
lineTo(x, y) 画线,两点连线,此时只是轮廓,还没有实际图形
closePath() 告诉 canvas,此次轮廓画完了
stroke() 画笔将轮廓线条描实
fill() 轮廓是封闭图形,填充颜色,默认填充色为黑色

二、绘图

1. 线段

1)基础使用

1
2
3
4
5
6
7
8
9
10
11
12
13
function draw () {
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d'); // 画笔

// 画一条直线
ctx.beginPath();
ctx.moveTo(50, 50); // 第一个点
ctx.lineTo(150, 50); // 第二个点
ctx.closePath();
ctx.stroke(); // 描实轮廓
}

draw();

可以给线段设置一些属性,如:线段宽度、线段颜色、线段与线段结合处过渡效果等等,要注意的是,这些属性都是全局属性。

2)设置线段颜色、宽度属性

属性 说明
strokeStyle=color 设置线段颜色
lineWidth=value 设置线段宽度
fillStyle=color 如果线段围成了封闭图形,可设置填充色
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
function draw () {
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');

// 原始线段
ctx.beginPath();
ctx.moveTo(20, 20);
ctx.lineTo(100, 20);
ctx.closePath();
ctx.stroke();

// 设置线段颜色
ctx.beginPath();
ctx.strokeStyle = 'rgb(255, 0, 0)';
ctx.moveTo(20, 40);
ctx.lineTo(100, 40);
ctx.closePath();
ctx.stroke();

// 设置线段宽度
ctx.beginPath();
ctx.lineWidth = 10;
ctx.moveTo(20, 70);
ctx.lineTo(100, 70);
ctx.closePath();
ctx.stroke();
}

draw();

可以看到,设置线段宽度那一段编码并未设置颜色但仍渲染出颜色,只因之前的代码设置过颜色,颜色应用之后所有的线段,是个全局属性。

canvas基础图3

3)设置粗线段两端样式

lineCap:粗线段两端样式,butt、round、square,具体效果见下图示。

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
function draw () {
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');

ctx.lineWidth = 20;

ctx.beginPath();
ctx.moveTo(30, 20);
ctx.lineTo(30, 100);
ctx.lineCap = 'butt'; // 默认
ctx.stroke();

ctx.beginPath();
ctx.moveTo(120, 20);
ctx.lineTo(120, 100);
ctx.lineCap = 'round'; // 粗线段两端多出一截,圆弧形状
ctx.stroke();

ctx.beginPath();
ctx.moveTo(200, 20);
ctx.lineTo(200, 100);
ctx.lineCap = 'square'; // 粗线段两端多出一截,方块形状
ctx.stroke();
}

draw();

canvas基础图4

4)设置粗线段与粗线段连接处样式

lineJoin:粗线段与粗线段连接处样式,round、bevel、miter,具体效果见下图示。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function draw () {
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');

var lineJoin = ['round', 'bevel', 'miter'];
ctx.lineWidth = 20;

for (var i = 0; i < lineJoin.length; i++){
ctx.lineJoin = lineJoin[i];
ctx.beginPath();
ctx.moveTo(50, 50 + i * 50);
ctx.lineTo(100, 100 + i * 50);
ctx.lineTo(150, 50 + i * 50);
ctx.lineTo(200, 100 + i * 50);
ctx.lineTo(250, 50 + i * 50);
ctx.stroke();
}

}

draw();

canvas基础图5

2. 三角形

与绘制线段类似,线段是一条线,三角形是三条线而已。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function draw () {
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d'); // 画笔

// 画三角形,描实边框用 stroke()
ctx.beginPath();
ctx.moveTo(50, 100); // 第一个点
ctx.lineTo(200, 100); // 第二个点
ctx.lineTo(125, 200); // 第三个点
ctx.closePath();
ctx.stroke();

// 画带填充色的三角形,只有闭合图形才能用 fill()
ctx.beginPath();
ctx.moveTo(50, 250); // 第一个点
ctx.lineTo(200, 250); // 第二个点
ctx.lineTo(125, 350); // 第三个点
ctx.closePath();
ctx.fill();
}

draw();

canvas基础图1

3. 矩形

绘制矩形有多重方法:

  • 路径绘制矩形(相对于三角形多画一条线段呗);
  • fillRect(x, y, width, height):画有填充色的矩形;
  • strokeRect(x, y, width, height):画只有边框的矩形;
  • clearRect(x, y, widh, height):在矩形内扣出一个矩形;
  • rect(x, y, widh, 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
function draw () {
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');

// 第一个矩形 fillRect()
ctx.fillRect(20, 20, 60, 60);

// 第二个矩形 strokeRect()
ctx.strokeRect(100, 20, 60, 60);

// 第三个矩形 clearRect()
ctx.fillRect(180, 20, 60, 60);
ctx.clearRect(200, 40, 20, 20);

// 第四个矩形 rect()
ctx.beginPath();
ctx.rect(260, 20, 60, 60);
ctx.fill();

// 第五个矩形 路径绘制
ctx.beginPath();
ctx.moveTo(340, 20);
ctx.lineTo(400, 20);
ctx.lineTo(400, 80);
ctx.lineTo(340, 80);
ctx.closePath();
ctx.stroke();
}

draw();

canvas基础图2

4. 圆弧和圆

1)arc(x, y, r, startAngle, endAngle, order)

x,y表示圆心位置,r为半径大小,startAngle和endAngle是始末位置角度,见下图,order为true表示逆时针绘制,order为false表示顺时针绘制。

数学中圆周长为 2πr,2π 表示整圆的弧度(360°),π 表示半圆的弧度(180°),π/2 表示四分之一圆的弧度(90°),在 js 中 Math.PI 表示数学中的 π。上面公式中 startAngle 和 endAngle 就表示始末位置弧度。

canvas基础图7

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function draw () {
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');

// 画半圆,顺时针画
ctx.beginPath();
ctx.arc(150, 150, 50, 0, Math.PI, false);
ctx.stroke();

// 画半圆,逆时针画
ctx.beginPath();
ctx.arc(300, 150, 50, 0, Math.PI, true);
ctx.stroke();

// 画整圆
ctx.beginPath();
ctx.arc(450, 150, 50, 0, 2*Math.PI, true);
ctx.stroke();

}

draw();

canvas基础图8

2)arcTo(x1, y1, x2, y2, r)

两点和半径确定一端弧线,dk 不喜欢用,就不写例子了。

5. 文本

  • strokeText(str, x, y):空心字;
  • fillText(str, x, y):实心字。
1
2
3
4
5
6
7
8
9
10
11
function draw () {
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');

ctx.font = '50px 宋体';
ctx.strokeText('dkvirus', 200, 100);
ctx.fillText('dkvirus', 200, 150);

}

draw();

canvas基础图6

书写文字还可以添加额外属性,如文字大小、文字字体、文字对齐方式等等。

属性 说明
font=’20px 宋体’ 设置字体大小、字体,默认字体 sans-serif
strokeStyle=’rgb(255, 0, 0, 0.5)’ 设置字体颜色
textAlign=value 设置字体对齐方式,value可填值有 left、center、right

6. 图片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function draw () {
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');

// Image 是 dom 里的 api
var img = new Image();
img.src = 'look.png';

// 请求图片为异步请求,监听事件等待图片完全加载好再用 canvas 绘制到画布上
img.onload = function () {
ctx.drawImage(img, 40, 40);
}

}

draw();

drawImage(img, x, y, width, height) 完整方法,其中 img 为图片的 dom 对象;(x,y) 为图片左上角的坐标点;width与height可以设置图片的大小,可以省略不写就是原图片大小。

canvas基础图10

7. 渐变

渐变有两种:线性渐变和径向渐变。所有能用 fillStyle 属性的图形都能添加渐变效果,只不过是将 fillStyle 的值由颜色换成了渐变色。

createLinearGradient(x1, y1, x2, y2) 创建线性渐变色,参数为两个点的坐标;
createRadialGradient(x1, y1, r1, x2, y2, r2) 创建径向渐变色,参数分别为内圆圆心和半径以及外圆的圆心和半径。

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
function draw() {
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');

// 创建径向渐变色
var grd = ctx.createRadialGradient(125, 160, 5, 130, 160, 100);
grd.addColorStop(0, "red");
grd.addColorStop(1, "white");

// 填充渐变
ctx.fillStyle = grd;
ctx.fillRect(50, 120, 150, 80);

// 创建线性渐变色
var grd2 = ctx.createLinearGradient(300, 0, 450, 0);
grd2.addColorStop(0, "red");
grd2.addColorStop(1, "white");

// 填充渐变
ctx.fillStyle = grd2;
ctx.fillRect(300, 120, 150, 80);

}

draw();

canvas基础图9

三、其它

1. 转换

1)translate:移动画布原点位置

ctx.translate(100,100);

2)rotate:以画布原点为轴心,旋转画布

ctx.rotate(-Math.PI/2) 默认顺时针旋转,参数为负数表示逆时针旋转,这里表示画布逆时针旋转 90°,连带画布里的文字也进行了旋转。

canvas基础图11

3)scale:缩放图形

ctx.scale(x, y) x 表示 x 轴方向上缩放倍数,y 表示 y 轴方向缩放倍数。

2. 合成

画图过程中不可避免会有图形重叠,当重叠时,如何设置样式?参考 菜鸟教程-globalCompositeOperation属性

3. 状态

save() 保存状态
restore() 恢复状态

canvas 的状态是什么??样式属性 + 转换属性。

4. 动画

四、练习

上面都是理论,在网上找到一个实战项目,源码也就 460 来行,可以用来熟悉如何用 canvas 写 h5 游戏,熟练之后可以写自己的小游戏。

canvas写中国象棋游戏

首页
友链
归档
dkvirus
动态
RSS