本系列文章均转自:我仍旧在这里(https://segmentfault.com/u/worengjiuzaizheli)
用户交互也许是我们学习canvas动画中首先需要掌握的部分。毕竟,如果没有交互或者向动画中做一些动态的输入,那么这跟看电影有什么区别呢?用户交互基于事件,一般来说包括:鼠标事件
,触摸事件
和键盘事件
。
1、事件和事件执行
在理解事件之前,你需要明白什么是listener
和handler
。
listener(即监听器)决定当一个事件发生时是否做出反应。handler(即执行者)是一个函数,当事件发生时被调用。好了,扯了这么多直接上代码:
1
2
3
4
5
|
element.addEventListener(
type, handler[, useCapture]);
type: 事件类型
handler: 事件执行函数
useCapture: 可选,为布尔值
false/
true, 表示在冒泡/捕获阶段执行
|
通过方法addEventListener
来为某一元素添加事件,具体到我们的canvas上是什么样的呢?加入我们现在想要在canvas上绑定一个mousedown
事件,具体代码如下:
1
2
3
|
canvas.addEventListener(
'mousedown',
function(event){
console.log(
"Mouse pressed on element");
},
false)
|
这样我们就为canvas绑定了鼠标点击事件,当在canvas上按下鼠标是就会在控制台看到打印出 “Mouse pressed on element”。
那么既然有添加事件(addEventListener
),就有移除事件(removeEventListener
),使用方式与添加事件几乎完全一样:
1
2
3
4
|
element.removeEventListener(
type, handler[, useCapture]);
type: 事件类型
handler: 事件执行函数
useCapture: 可选,为布尔值
false/
true, 表示在冒泡/捕获阶段执行
|
唯一需要注意的是handler
,即移除事件的函数,这里只能写函数名,而不能像添加事件一样将整个功能函数全部写入。也就是说,在添加某个事件的时候,我们可以将需要执行的函数写在事件监听之外并命名,这样如果你想要在后续的代码中移除该事件,直接将函数名传入移除事件的handler
中即可。
现在让我们来实验下先为canvas添加一个事件,再将其移除
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
<body>
<canvas id="canvas" width="500" height="500">
</canvas>
<script>
</script>
<script>
window.onload = function(){
var canvas = document.getElementById('canvas');
function add(event){
console.log("mouse down");
}
canvas.addEventListener('mousedown', add, false);
canvas.removeEventListener('mousedown', add, false)
}
</script>
</body>
|
现在你可以看看控制台是否还能打印出“mouse down”!
2.鼠标事件
鼠标事件一共可以分为:
- mousedown
- mouseup
- click
- dbclick
- mousewheel
- mouseover
- mouseout
每一个鼠标事件都包含两个属性来决定当前鼠标的位置:pageX
和pageY
。通过pageX
和pageY
,还有canvas元素的偏移位置,我们就能够计算出鼠标具体是在canvas元素的什么位置。为了考虑不同浏览器的兼容性,以防万一你可以使用clientX
和clientY
。在这里,我们创建一个js文件,名为**utils.js**
,这个文件是我们的一个工具函数,里面会逐渐加入一些我们重复使用的方法,那么现在我们向我们的工具函数中添加第一个方法captureMouse
,具体代码如下:
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
|
utils.js文件
window.utils = {};
window.utils.captureMouse =
function(element){
var mouse = {
x:
0,
y:
0};
element.addEventListener(
'mousemove',
function(event){
var x,y;
if(event.pageX||event.pageY){
x = event.pageX;
y = event.pageY;
}
else{
x = event.clientX +
document.body.scrollLeft +
document.documentElement.scrollLeft;
y = event.clientY +
document.body.scrollTop +
document.documentElement.scrollTop;
}
x -= element.offsetLeft;
y -= element.offsetTop;
mouse.x = x;
mouse.y = y;
},
false);
return mouse;
}
|
这个方法将DOM元素作为参数传入,这样我们只要将canvas传入就可以获取到鼠标在当前canvas的位置。具体代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
<canvas id="canvas" width='500' height="500" style="background:#000">
<p>you browser not support canvas!
<p>
</canvas>
<script src='../js/utils.js'>
</script>
<script>
window.onload = function(){
var canvas = document.getElementById('canvas'),
mouse = utils.captureMouse(canvas);
canvas.addEventListener('mousedown',function(event){
console.log("x:" +mouse.x +",y:" + mouse.y);
});
</script>
|
Have a try!!!看看能否成功。
3、getBoundingClientRect()
其实,关于canvas的鼠标位置获取的方法还可以应用它自身的一个方法getBoundingClientRect
,这里做一个介绍,你可以使用,但本系列文章主要使用上面这种更具广泛性的方法。具体代码可以参考如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
canvas.addEventListener(
'mousedown',
function(event){
var event = event ||
window.event;
var winX = event.clientX+
document.body.scrollLeft +
document.documentElement.scrollLeft || event.pageX;
var winY = event.clientY+
document.body.scrollTop +
document.documentElement.scrollTop || event.pageY;
var can = {
x:
0,
y:
0};
var canBox = canvas.getBoundingClientRect();
can.x = (winX - canBox.left)
(canvas.width/canBox.width);
can.y = (winY - canBox.top)(canvas.height/canBox.height);
console.log(can.x,can.y);
},
false);
|
4、键盘事件
键盘事件就两个:
我们同样可以向绑定鼠标事件那样为canvas绑定键盘事件。好吧!现在我们来看看,如何将一个键盘事件绑定到window(为什么不直接绑定到canvas上呢?想想)上:
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
|
<body >
<p>任意按下按键
</p>
<script>
window.onload = function(){
function onKeyboard(event){
switch (event.keyCode){
case 38:
console.log('up!');
break;
case 40:
console.log('down!');
break;
case 37:
console.log('left!');
break;
case 39:
console.log('right!');
break;
default:
console.log(event.keyCode);
}
}
window.addEventListener('keydown',onKeyboard,false);
}
</script>
</body>
|
试一试,当按下鼠标的方向键是是否在控制台打印出了相应的信息!
5、触摸事件
触摸事件包括以下3种:
- touchstart
- touchend
- touchmove
触摸实践中,手指就充当了鼠标的作用。同样我们最为关心的是当前触摸的位置。和captureMouse
方法一样,这里在我们的工具函数文件中,需要添加一新的方法来捕获触摸的位置,名为captureTouch
,现在在utils.js文件中添加如下方法:
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
|
utils.js文件
window.utils.captureTouch =
function (element) {
var touch = {
x:
null,
y:
null,
isPressed:
false,
event:
null
};
var body_scrollLeft =
document.body.scrollLeft,
element_scrollLeft =
document.documentElement.scrollLeft,
body_scrollTop =
document.body.scrollTop,
element_scrollTop =
document.documentElement.scrollTop,
offsetLeft = element.offsetLeft,
offsetTop = element.offsetTop;
element.addEventListener(
'touchstart',
function (event) {
touch.isPressed =
true;
touch.event = event;
},
false);
element.addEventListener(
'touchend',
function (event) {
touch.isPressed =
false;
touch.x =
null;
touch.y =
null;
touch.event = event;
},
false);
element.addEventListener(
'touchmove',
function (event) {
var x, y,
touch_event = event.touches[
0];
if (touch_event.pageX || touch_event.pageY) {
x = touch_event.pageX;
y = touch_event.pageY;
}
else {
x = touch_event.clientX + body_scrollLeft + element_scrollLeft;
y = touch_event.clientY + body_scrollTop + element_scrollTop;
}
x -= offsetLeft;
y -= offsetTop;
touch.x = x;
touch.y = y;
touch.event = event;
},
false);
return touch;
};
|
总结
这一节主要介绍用户与canvas交互的各种事件,重要的是你应该在你自己的工具函数文件中包含了以下两个方法:utils.captureTouch
和utils.captureMouse
这两个方法都是为了获取当前相对于canvas元素的位置。我们将在后面的章节中频繁使用。当然,除了这两个方法,由于我们使用的requestAnimationFrame
方法同样也涉及到兼容性的问题,我们将它一同添加到utils.js
中,具体代码请查看utils.js
文件。
下一节,三角函数坐标旋转敬请期待!!!