canvas2D绘图

canvas2D绘图

基本使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- Canvas标签的默认大小为:300 x 150 (像素),而这里咱们设置为了:200 x 200(像素)。
Canvas标签中的文字是在不支持Canvas标签的浏览器中使用的,因为支持Canvas标签的浏览器会忽略容器中包含的内 容正常渲染Canvas标签,而不支持Canvas标签的浏览器则相反,浏览器会忽略容器而显示其中的内容 -->
<canvas width="200" height="200">

</canvas>
</body>
</html>

渲染上下文

canvas标签提供了一个容器画布,如果想要进行绘制就得找到渲染上下文

getContext()

getContext方法是有一个接收参数,它是绘图上下文的类型

2d:建立一个二维渲染上下文。这种情况可以用 CanvasRenderingContext2D()来替换getContext(‘2d’)。

webgl(或 experimental-webgl): 创建一个 WebGLRenderingContext 三维渲染上下文对象。只在实现WebGL 版本1(OpenGL ES 2.0)的浏览器上可用。

webgl2(或 experimental-webgl2):创建一个 WebGL2RenderingContext 三维渲染上下文对象。只在实现 WebGL 版本2 (OpenGL ES 3.0)的浏览器上可用。

bitmaprenderer:创建一个只提供将canvas内容替换为指定ImageBitmap功能的ImageBitmapRenderingContext。

1
2
3
4
5
6
7
8
9
10
11
<canvas width="200" height="200" id="canvas">
当前浏览器不支持canvas元素,请升级或者更换浏览器
</canvas>
<script>
let canvas = document.getElementById('canvas')
console.log(canvas.getContext)
if(canvas.getContext){
let ctx = canvas.getContext('2d')

}
</script>

在获取上下文之后就可以绘制基本形状

绘制形状

直线
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
moveTo(x, y)
设置初始位置,参数为初始位置x和y的坐标点

lineTo(x, y)
绘制一条从初始位置到指定位置的直线,参数为指定位置x和y的坐标点

stroke()
通过线条来绘制图形轮廓

if(canvas.getContext){
let ctx = canvas.getContext('2d')
ctx.moveTo(50,50)
ctx.lineTo(300,300)
ctx.stroke()
}
三角形
1
2
3
4
5
6
7
8
if(canvas.getContext){
let ctx = canvas.getContext('2d')
ctx.moveTo(50,50) //起点坐标
ctx.lineTo(300,300)
ctx.lineTo(50,300)
ctx.lineTo(50,50) //终点坐标。闭合点
ctx.stroke()
}

矩形

矩形的绘制并不是单纯的直线拼凑,canvas提供了相关api绘制矩形

strokeRect(x, y, width, height) 绘制一个矩形的边框

fillRect(x, y, width, height) 绘制一个填充的矩形

clearRect(x, y, width, height) 清除指定矩形区域,让清除部分完全透明。

1
2
3
4
// 矩形
ctx.strokeRect(50,50,200,100)
ctx.fillRect(50,160,200,100)
ctx.clearRect(60,180,50,50

圆弧和圆

arc(x, y, radius, startAngle, endAngle, anticlockwise)。x和Y为圆心的坐标,radius为半径,startAngle为圆弧或圆的开始位置,endAngle为圆弧或圆的结束位置,anticlockwise是绘制的方向(不写默认为false,从顺时针方向)

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
// 原型和弧
ctx.arc(60, 60, 50, 0, Math.PI, false);
ctx.stroke()

需要注意的是:在画弧的时候,arc()函数中角的单位是弧度而不是角度。角度换算为弧度的表达式为:弧度=(Math.PI/180)*角度。

// 原型和弧
// ctx.arc(60, 60, 50, 0, Math.PI, false);
// ctx.stroke()

// // 绘制一个圆弧
// ctx.arc(200, 60, 50, 0, Math.PI*2, false);
// ctx.stroke();

// 如果按照上述写法绘制一根弧线和圆 会出现路径相连,因此需要开启和闭合路径
// beginPath
// 新建一条路径,生成之后,图形绘制命令被指向到路径上。

// closePath
// 闭合路径之后图形绘制命令又重新指向到上下文中。 具体怎么使用这两个函数呢?下面咱们介绍一下,直接上代码:
// 原型和弧
ctx.beginPath()
ctx.arc(60, 60, 50, 0, Math.PI, false);
ctx.fill(); //填充黑色
ctx.stroke()
ctx.closePath()
// 绘制一个圆弧
ctx.beginPath()
ctx.arc(200, 60, 50, 0, Math.PI*2, false);
ctx.fill();
ctx.stroke()
ctx.closePath()

在咱们开启和关闭路径的时候,关闭路径其实并不是必须的,对于新路径其实每次都开启新路径就ok。

填充fill

1
2
3
4
5
6
// 绘制一个圆弧
ctx.beginPath()
ctx.arc(200, 60, 50, 0, Math.PI*2, false);
ctx.fill();
ctx.stroke()
ctx.closePath()
椭圆

ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise)

  • x、y:椭圆的圆心位置
  • radiusX、radiusY:x轴和y轴的半径
  • rotation:椭圆的旋转角度,以弧度表示
  • startAngle:开始绘制点
  • endAngle:结束绘制点
  • anticlockwise:绘制的方向(默认顺时针),可选参数。
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
结合了一下,有点搞笑
// 椭圆
ctx.beginPath();
ctx.ellipse(100, 150, 50, 100, 0, 0, 2 * Math.PI);
ctx.stroke();

ctx.beginPath()
ctx.arc(100, 150, 50, 0, Math.PI*2, false);
ctx.fill();
ctx.stroke()
ctx.closePath()

ctx.beginPath();
ctx.ellipse(400, 150, 50, 100, 0, 0, 2 * Math.PI);
ctx.stroke();

ctx.beginPath()
ctx.arc(400, 150, 50, 0, Math.PI*2, false);
ctx.fill();
ctx.stroke()
ctx.closePath()

ctx.beginPath();
ctx.ellipse(250, 350, 20, 200, Math.PI/2, 0, 2 * Math.PI); // 旋转90°
ctx.fill();

贝塞尔曲线
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 // 贝塞尔曲线
// 贝塞尔曲线一般用来绘制复杂有规律的图形,在Canvas中也是一个十分有用的路径类型。
// 二次贝塞尔曲线
// 语法:quadraticCurveTo(cp1x, cp1y, x, y),其中cp1x和cp1y为一个控制点,x和y为结束点
// 绘制一段二次贝塞尔曲线
ctx.moveTo(50, 50);
ctx.quadraticCurveTo(200, 200, 350, 50);
// 绘制
ctx.stroke();

// 三次贝塞尔曲线
// 和二次贝塞尔曲线不同的是三次贝塞尔曲线有两个控制点。
// 语法:ctx.bezierCurveTo(cp1x,cp1y, cp2x,cp2y, x, y),其中cp1x和cp1y为一个控制点,cp2x和cp2y为第二个控制点,x和y为结束点。
ctx.beginPath() // 开启路径
ctx.moveTo(50, 200);
ctx.bezierCurveTo(150, 50, 250, 350, 350, 200);
// 绘制
ctx.stroke();

绘制样式

线条样式

lineWidth

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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
let canvas = document.getElementById('canvas')
console.log(canvas.getContext)
if(canvas.getContext){
let ctx = canvas.getContext('2d')
// 线条样式
// lineWidth 设置当前绘线的粗细。属性值必须为正数。默认值是 1.0。
// lineCap
// lineCap 设置线段端点显示的样子。可选值为:butt,round 和 square。默认是 butt。
// lineJoin
// lineJoin 该属性可以设置两线段连接处所显示的样子。可选值为:round, bevel 和 miter。默认是
// ctx.lineWidth = 10;
// ctx.lineCap='round'
// ctx.moveTo(50,50)
// ctx.lineTo(300,300)
// ctx.stroke()

// ctx.beginPath()
// ctx.lineWidth = 10;
// ctx.lineJoin='miter'
// ctx.moveTo(50, 20);
// ctx.lineTo(100, 60);
// ctx.lineTo(150, 20);
// ctx.lineTo(200, 60);
// ctx.lineTo(250, 20);
// ctx.stroke();
// ctx.closePath();

// miterLimit
// miterLimit 限制当两条线相交时交接处最大长度;所谓交接处长度(斜接长度)是指线条交接处内角顶点到外角顶点的长度。
// 线段之间夹角比较大时,交点不会太远,但随着夹角变小,交点距离会呈指数级增大。
// 如果交点距离大于miterLimit值,连接效果会变成了 lineJoin = bevel 的效果。
// ctx.beginPath()
// ctx.lineWidth = 5;
// ctx.lineJoin='miter'
// ctx.miterLimit = 10
// ctx.moveTo(0, 100);
// for (i = 0; i < 30 ; i++) {
// var dy = i % 2 == 0 ? 200 : 100;
// ctx.lineTo(Math.pow(i, 1.5) * 2, dy);
// }
// ctx.stroke();
// ctx.closePath();


// setLineDash/getLineDash
// setLineDash 可以设置当前虚线样式。
// getLineDash 则是返回当前虚线设置的样式,长度为非负偶数的数组。
// ctx.setLineDash([5, 10, 20]);
// console.log(ctx.getLineDash()); // [5, 10, 20, 5, 10, 20]
// ctx.beginPath();
// ctx.moveTo(0,100);
// ctx.lineTo(400, 100);
// ctx.stroke();
// // 再绘制一条虚线
// ctx.setLineDash([5, 10, 20, 40]);
// console.log(ctx.getLineDash()); // [5, 10, 20, 40]
// ctx.beginPath();
// ctx.moveTo(0,200);
// ctx.lineTo(400, 200);
// ctx.stroke();

// lineDashOffset
// lineDashOffset 设置虚线样式的起始偏移量
// 绘制一条虚线
// ctx.setLineDash([5, 10, 20]);
// console.log(ctx.getLineDash()); // [5, 10, 20, 5, 10, 20]
// ctx.beginPath();
// ctx.moveTo(0,100);
// ctx.lineTo(400, 100);
// ctx.stroke();
// // 再绘制一条虚线
// ctx.setLineDash([5, 10, 20, 40]);
// console.log(ctx.getLineDash()); // [5, 10, 20, 40]
// ctx.beginPath();
// ctx.moveTo(0,200);
// ctx.lineTo(400, 200);
// ctx.stroke();

// 设置 globalAlpha 属性或者使用有透明度的样式作为轮廓或填充都可以实现
// 绘制一个矩形
// ctx.beginPath();
// // 指定透明度的填充样式
// ctx.fillStyle = "rgba(0, 255, 0, 0.2)";
// ctx.fillRect(10,10,300,100);
// // 绘制一个矩形边框
// ctx.beginPath();
// // 指定透明度的描边样式
// ctx.strokeStyle = "rgba(255, 0, 0, 0.7)";
// ctx.strokeRect(10, 90, 100, 300);
// // 绘制一个圆
// ctx.beginPath()
// ctx.fillStyle = "rgba(255, 255, 0, 1)";
// // 设置透明度值
// ctx.globalAlpha = 0.5;
// ctx.arc(200, 200, 100, 0, Math.PI*2, true);
// ctx.fill();

// 渐变
// 线性渐变和径向渐变
// 线性渐变
// 语法: createLinearGradient(x1, y1, x2, y2),参数分别为 起点的坐标和终点的坐标。
// 在渐变的设置中还需要一个方法来添加渐变的颜色,语法为:gradient.addColorStop(offset, color),
// 其中color就是颜色,offset 则是颜色的偏移值,只为0到1之间的数。
// 创建渐变
// var gradient1 = ctx.createLinearGradient(10, 10, 400, 10);
// gradient1.addColorStop(0, "#00ff00");
// gradient1.addColorStop(1, "#ff0000");
// var gradient2 = ctx.createLinearGradient(10, 10, 400, 10);
// // 从0.5的位置才开始渐变
// gradient2.addColorStop(0.5, "#00ff00");
// gradient2.addColorStop(1, "#ff0000");
// ctx.beginPath()
// ctx.fillStyle = gradient1;
// ctx.fillRect(10, 10, 400, 100);
// ctx.beginPath();
// ctx.fillStyle = gradient2;
// ctx.fillRect(10, 150, 400, 100);

// 径向渐变
// ctx.createRadialGradient(x0, y0, r0, x1, y1, r1),参数分别为开始圆的坐标和半径以及结束圆的坐标和半径。
// 结束坐标为点
// var gradient1 = ctx.createRadialGradient(100, 100, 100, 100, 100, 0);
// gradient1.addColorStop(0, "#ff770f");
// gradient1.addColorStop(1, "#ffffff");
// // 结束坐标为半径30的圆
// var gradient2 = ctx.createRadialGradient(320, 100, 100, 320, 100, 30);
// gradient2.addColorStop(0, "#ff770f");
// gradient2.addColorStop(1, "#ffffff");
// // 从0.5的位置才开始渲染
// var gradient3 = ctx.createRadialGradient(100, 320, 100, 100, 320, 0);
// gradient3.addColorStop(0.5, "#ff770f");
// gradient3.addColorStop(1, "#ffffff");
// // 开始坐标和结束坐标不一样
// var gradient4 = ctx.createRadialGradient(320, 320, 100, 250, 250, 0);
// gradient4.addColorStop(0, "#ff770f");
// gradient4.addColorStop(1, "#ffffff");
// ctx.beginPath();
// ctx.fillStyle = gradient1;
// ctx.fillRect(10, 10, 200, 200);
// ctx.beginPath();
// ctx.fillStyle = gradient2;
// ctx.fillRect(220, 10, 200, 200);
// ctx.beginPath();
// ctx.fillStyle = gradient3;
// ctx.fillRect(10, 220, 200, 200);
// ctx.beginPath();
// ctx.fillStyle = gradient4;
// ctx.fillRect(220, 220, 200, 200);

// Canvas中想绘制图案效果,需要用 createPattern 方法来实现。
// 语法:createPattern(image, type),参数分别为:Image 参数可以是一个 Image 对象,也可以是一个 canvas 对象,Type 为图案绘制的类型,可用的类型分别有:repeat,repeat-x,repeat-y 和 no-repeat。
// 创建一个 image对象
// var img = new Image();
// img.src = "./image.png";
// img.onload = function() {
// // 图片加载完以后
// // 创建图案
// var ptrn = ctx.createPattern(img, 'no-repeat');
// ctx.fillStyle = ptrn;
// ctx.fillRect(0, 0, 500, 500);
// }


}

loading……

透明度
渐变
图案样式

绘制文本

strokeText描边
fillText填充
文本样式
阴影

绘制图片

drawImage

变形

状态的保存和恢复
移动、旋转和缩放
transform,setTransform,resetTransform

合成与裁剪

合成
裁剪

动画

高级动画

绘制小球
速率
边界
加速度
拖尾效果

应用

保存图片
反相颜色
像素数据

跟着掘金上的一篇文章学习的

作者:ndz链接:https://juejin.cn/post/7119495608938790942来源:稀土掘金著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。