canvas事件处理

  目录

canvas中的图形添加事件

canvas事件处理

canvas是一块画布,假设这块画布中有3个方块,给这3个方块添加事件该如何操作呢?
因为canvas是一个元素节点,所以添加事件只能添加到这个canvas上,canvas里边的图形要响应事件稍微复杂些。
这里用到了canvas提供的api isPointInPath,这个api可能会有兼容性问题,但本次还是基于这个api实现。
笔者这次只实现了mousedown事件的基础功能,而且图形是固定的,先看看实现的这个事件监听类:

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
/**
* @desc canvas事件处理类
* @params canvas 要监听的图形所在canvas
* @method pushPath 监听图形
* @method iteratorRegsions 便利所要监听的所有图形
*/
function RegsionEvt(canvas) {
this.canvas = document.createElement('canvas');
this.canvas.width = canvas.width;
this.canvas.height = canvas.height;
this.ctx = this.canvas.getContext("2d");
this.arr = [];
/**
* option.shapType 类型
* option.x
* option.y
* option.width
* option.height
* option.evtName
* option.CallBack
*/
this.pushPath = function(option) {
this.arr.push(option);
}
/**
* evtName 事件名
* evt 事件对象
*/
this.iteratorRegsions = function(evtName, evt) {
this.arr.forEach(function(item) {
this.ctx.beginPath();
if(item.shapType==='rect' && item.evtName===evtName) {
this.ctx.rect(item.x, item.y, item.width, item.height);
if(this.ctx.isPointInPath(evt.layerX, evt.layerY)) {
item.CallBack(evt);
}
}
this.ctx.closePath();
});
}
}

使用的时候,new一个实例,构造函数参数是要监听的图形所在的canvas,添加图形事件需要调用pushPath方法,触发事件的时候需要循环遍历添加了事件的图形,方法是iteratorRegsions。
最后,附上一个demo:

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
<!DOCTYPE html>
<html>
<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>canvas-event</title>
</head>
<style>
* {
margin: 0;
padding: 0;
}
</style>
<body>
<canvas id="canvas" width="500" height="300" style="display: block; border: 1px solid #cccccc; margin: 50px auto;"></canvas>
</body>
<script>
var nCanvas = document.getElementById('canvas');
var ctx = nCanvas.getContext("2d");
var regsion = new RegsionEvt(nCanvas);

ctx.beginPath();
ctx.rect(50, 50, 100, 100);
ctx.fillStyle = 'red';
ctx.fill();
regsion.pushPath({
shapType: 'rect',
evtName: 'mousedown',
x: 50,
y: 50,
width: 100,
height: 100,
CallBack: function(evt) {
console.log('红色box被点击了');
}
});

ctx.beginPath();
ctx.rect(250, 150, 100, 100);
ctx.fillStyle = 'yellow';
ctx.fill();
regsion.pushPath({
shapType: 'rect',
evtName: 'mousedown',
x: 250,
y: 150,
width: 100,
height: 100,
CallBack: function(evt) {
console.log('黄色box被点击了');
}
});

ctx.beginPath();
ctx.rect(350, 50, 50, 50);
ctx.fillStyle = 'green';
ctx.fill();
regsion.pushPath({
shapType: 'rect',
evtName: 'mousedown',
x: 350,
y: 50,
width: 50,
height: 50,
CallBack: function(evt) {
console.log('绿色box被点击了');
}
});

nCanvas.onmousedown = function(evt) {
regsion.iteratorRegsions('mousedown', evt);
}

/**
* @desc canvas事件处理类
* @params canvas 要监听的图形所在canvas
* @method pushPath 监听图形
* @method iteratorRegsions 便利所要监听的所有图形
*/
function RegsionEvt(canvas) {
this.canvas = document.createElement('canvas');
this.canvas.width = canvas.width;
this.canvas.height = canvas.height;
this.ctx = this.canvas.getContext("2d");
this.arr = [];
/**
* option.shapType 类型
* option.x
* option.y
* option.width
* option.height
* option.evtName
* option.CallBack
*/
this.pushPath = function(option) {
this.arr.push(option);
}
/**
* evtName 事件名
* evt 事件对象
*/
this.iteratorRegsions = function(evtName, evt) {
this.arr.forEach(function(item) {
this.ctx.beginPath();
if(item.shapType==='rect' && item.evtName===evtName) {
this.ctx.rect(item.x, item.y, item.width, item.height);
if(this.ctx.isPointInPath(evt.layerX, evt.layerY)) {
item.CallBack(evt);
}
}
this.ctx.closePath();
});
}
}
</script>
</html>