使用canvas制作画图板

原理:在canvas画布上捕捉鼠标(手指)动作,关注下笔、拖动、抬笔三个事件。

下笔使用onmousedown/ontouchstart,拖动使用onmousemove/ontouchmove,抬笔使用onmouseup/ontouchend,同时需要检测笔尖是否移动到画布外(onmouseout)。

在这三个事件被捕捉后,就能顺利的在画布上生成图像了。

在画布上自由画画:

Html:

1
<canvas id="canvas" width="1024" height="665"></canvas>

Javascript:

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
var canvas = document.getElementById('canvas');
var can = canvas.getContext('2d');
//定义画布

/****使用自由画笔****/
function Brush(){
canvas.ontouchstart = function(e) {
e = window.event || e;
var sX = e.pageX - this.offsetLeft;
var sY = e.pageY - this.offsetTop;
//获取起始坐标
can.beginPath();
can.moveTo(sX, sY);
status = 1;
}
//画笔移动的时候
canvas.ontouchmove = function(e) {
e = window.event || e;
var eX = e.pageX - this.offsetLeft;
var eY = e.pageY - this.offsetTop;
if(status == 1) {
can.lineTo(eX, eY);
can.stroke();
} else {
return false;
}
}
//画笔抬起的时候
canvas.ontouchend = function() {
can.closePath();
}
}
Brush();

通过以上代码可以实现在画布上自由绘画。

用按钮触发以上函数可实现选择“自由画笔工具”绘画。

相似的,画直线、画圆形、画矩形也是如此:

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
/****画直线****/
function Line(){
canvas.ontouchstart = function(e) {
e = window.event || e;
sX = e.pageX - this.offsetLeft;
sY = e.pageY - this.offsetTop;
can.beginPath();
can.moveTo(sX, sY);
}
canvas.ontouchmove = function(e) {
}
//画笔抬起时,画笔位置为终点
canvas.ontouchend = function(e) {
e = window.event || e;
var eX = e.pageX - this.offsetLeft;
var eY = e.pageY - this.offsetTop;
can.lineTo(eX, eY);
can.closePath();
can.stroke();
}
}

/****画空心圆形****/
function Arc(){
canvas.ontouchstart = function(e) {
e = window.event || e;
sX = e.pageX - this.offsetLeft;
sY = e.pageY - this.offsetTop;
}
//画空心圆,鼠标抬起时,当前画笔位置为外圆结束点
canvas.ontouchend = function(e) {
e = window.event || e;
var eX = e.pageX - this.offsetLeft;
var eY = e.pageY - this.offsetTop;
var dX = eX - sX
var dY = eY - sY;
var r = Math.sqrt(Math.pow(dX, 2) + Math.pow(dY, 2));
//计算出半径
can.beginPath();
can.arc(sX, sY, r, 0, 360, false);
can.closePath();
can.stroke();
}
}

/****画矩形****/
function Rect(){
canvas.ontouchstart = function(e) {
e = window.event || e;
sX = e.pageX - this.offsetLeft;
sY = e.pageY - this.offsetTop;
}
//画空心矩形,画笔抬起时,当前画笔位置为矩形的右下角
canvas.ontouchend = function(e) {
e = window.event || e;
var eX = e.pageX - this.offsetLeft;
var eY = e.pageY - this.offsetTop;
var w = eX - sX; //矩形的宽
var h = eY - sY; //矩形的高
can.strokeRect(sX, sY, w, h);
}
}

通过以上代码可以实现简单的画图板。但是会产生一个问题:画矩形与圆形时 在画笔移动时,画布上不会产生相应的图形,只有在画笔抬起时才会产生图像,所以在画画的时候感知不到自己纠结画出的图形是怎样的,这样的体验非常差。因此,使用双画布来解决这个问题,即在本来的画布上放一个同样大小的画布,移动画笔的时候在临时画布上不断地清除、绘制图像就能使用户感知到画画的过程。

临时画布需要设置position:absolute与z-index来与主画布重叠。

1
2
3
4
/****清除临时画布的函数****/
function clearContext(){
can_bak.clearRect(0, 0, 1024, 665);
}

例如画圆形时,加上

1
2
3
4
5
6
7
8
9
10
11
12
13
canvas_bak.ontouchmove = function(e) {
e = window.event || e;
clearContext();
var eX = e.pageX - this.offsetLeft;
var eY = e.pageY - this.offsetTop;
var dX = eX - sX
var dY = eY - sY;
var r = Math.sqrt(Math.pow(dX, 2) + Math.pow(dY, 2));
can_bak.beginPath();
can_bak.arc(sX, sY, r, 0, 360, false);
can_bak.closePath();
can_bak.stroke();
}

在ontouchend中加上clearContext();即可。

最终效果:

upload successful