canvas动画包教不包会:用户交互
没有用户交互的动画就跟电视上的动画片一样,不管谁看,都是一个样,千年不变。显然,这不是我们想要的,很多时候,我们需要用户参与进来,这样才能产生丰富的动画效果,这就是专门用一章来了解用户交互的原因。
function MClick(event){
console.log('鼠标点击了canvas');
};
canvas.addEventListener('mousedown',MClick,false);
canvas.removeEventListener('mousedown',MClick,false);
mousedown
mouseup
click
dblclick
mousewheel
mousemove
mouseover
mouseout
canvas.addEventListener('mousedown',function(event){
var x = (event.pageX || event.clientX + document.body.scrollLeft +document.documentElement.scrollLeft) - canvas.offsetLeft;
var y = (event.pageY || event.clientY + document.body.scrollTop +document.documentElement.scrollTop) - canvas.offsetTop;
},false);
window.tool = {};
window.tool.captureMouse = function(element,mousedown,mousemove,mouseup){
/*传入Event对象*/
function getPoint(event){
event = event || window.event; /*为了兼容IE*/
/*将当前的鼠标坐标值减去元素的偏移位置,返回鼠标相对于element的坐标值*/
var x = (event.pageX || event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft);
x -= element.offsetLeft;
var y = (event.pageY || event.clientY + document.body.scrollTop + document.documentElement.scrollTop);
y -= element.offsetTop;
return {x:x,y:y};
};
if(!element) return;
/*为element元素绑定mousedown事件*/
element.addEventListener('mousedown',function(event){
event.point = getPoint(event);
mousedown && mousedown.call(this,event);
},false);
/*为element元素绑定mousemove事件*/
element.addEventListener('mousemove',function(event){
event.point = getPoint(event);
mousemove && mousemove.call(this,event);
},false);
/*为element元素绑定mouseup事件*/
element.addEventListener('mouseup',function(event){
event.point = getPoint(event);
mouseup && mouseup.call(this,event);
},false);
};
/*回调函数会传入一个event对象,event.point中包含了x和y属性,分别对应鼠标相对element的X坐标和Y坐标,函数内的this指向绑定元素element*/
function mousedown(event) {
console.log(event.point.x,event.ponit.y);
console.log(this);
document.querySelector('.pointX').innerHTML = event.point.x;
document.querySelector('.pointY').innerHTML = event.point.y;
};
function mousemove(event) {
console.log(event.point);
document.querySelector('.pointX1').innerHTML = event.point.x;
document.querySelector('.pointY1').innerHTML = event.point.y;
var x = event.point.x;
var y = event.point.y;
var radius = 5;
/*清除整个canvas画布*/
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.fillStyle = 'red';
ctx.beginPath();
/*绘制一个跟随鼠标的圆*/
ctx.arc(x,y,radius,0,2*Math.PI,true);
ctx.fill();
ctx.closePath();
};
function mouseup(event) {
console.log(event.point);
document.querySelector('.pointX2').innerHTML = event.point.x;
document.querySelector('.pointY2').innerHTML = event.point.y;
};
/*传入canvas元素,后面是传入三个函数,分别对应mousedown、mousemove和mouseup事件的事件处理函数*/
tool.captureMouse(canvas, mousedown, mousemove, mouseup);
touchstart
touchmove
touchend
canvas.addEventListener('touchstart',function(event){
var touchEvnet = event.changedTouches[0];
var x = (touchEvent.pageX || touchEvent.clientX + document.body.scrollLeft+ document.documentElement.scrollLeft );
x -= canvas.offsetLeft;
var y = (touchEvent.pageY || touchEvent.clientY + document.body.scrollTop + document.documentElement.scrollTop );
y -= canvas.offsetTop;
});
window.tool.captureTouch = function(element,touchstart,touchmove,touchend){
/*传入Event对象*/
function getPoint(event){
event = event || window.event;
var touchEvent = event.changedTouches[0];
/*将当前的鼠标坐标值减去元素的偏移位置,返回鼠标相对于element的坐标值*/
var x = (touchEvent.pageX || touchEvent.clientX + document.body.scrollLeft + document.documentElement.scrollLeft);
x -= element.offsetLeft;
var y = (touchEvent.pageY || touchEvent.clientY + document.body.scrollTop + document.documentElement.scrollTop);
y -= element.offsetTop;
return {x:x,y:y};
};
if(!element) return;
/*为element元素绑定touchstart事件*/
element.addEventListener('touchstart',function(event){
event.point = getPoint(event);
touchstart && touchstart.call(this,event);
},false);
/*为element元素绑定touchmove事件*/
element.addEventListener('touchmove',function(event){
event.point = getPoint(event);
touchmove && touchmove.call(this,event);
},false);
/*为element元素绑定touchend事件*/
element.addEventListener('touchend',function(event){
event.point = getPoint(event);
touchend && touchend.call(this,event);
},false);
};
window.tool.captureMT = function(element, touchStartEvent, touchMoveEvent, touchEndEvent) {
'use strict';
var isTouch = ('ontouchend' in document);
var touchstart = null;
var touchmove = null
var touchend = null;
if(isTouch){
touchstart = 'touchstart';
touchmove = 'touchmove';
touchend = 'touchend';
}else{
touchstart = 'mousedown';
touchmove = 'mousemove';
touchend = 'mouseup';
};
/*传入Event对象*/
function getPoint(event) {
/*将当前的触摸点坐标值减去元素的偏移位置,返回触摸点相对于element的坐标值*/ event = event || window.event;
var touchEvent = isTouch ? event.changedTouches[0]:event;
var x = (touchEvent.pageX || touchEvent.clientX + document.body.scrollLeft + document.documentElement.scrollLeft);
x -= element.offsetLeft;
var y = (touchEvent.pageY || touchEvent.clientY + document.body.scrollTop + document.documentElement.scrollTop);
y -= element.offsetTop;
return {x: x,y: y};
};
if(!element) return;
/*为element元素绑定touchstart事件*/
element.addEventListener(touchstart, function(event) {
event.point = getPoint(event);
touchStartEvent && touchStartEvent.call(this, event);
}, false);
/*为element元素绑定touchmove事件*/
element.addEventListener(touchmove, function(event) {
event.point = getPoint(event);
touchMoveEvent && touchMoveEvent.call(this, event);
}, false);
/*为element元素绑定touchend事件*/
element.addEventListener(touchend, function(event) {
event.point = getPoint(event);
touchEndEvent && touchEndEvent.call(this, event);
}, false);
};
在上面的代码中,我们先检测是移动还是PC('ontouchend' in document),然后将布尔值传给变量 isTouch ,然后定义使用mouse事件还是touch事件,获取坐标点时,也是根据 isTouch的值来绝对直接用 event还是用 event.changedTouches[0] 。
实例(移动PC都可以使用):
4、键盘事件
键盘事件只有三个:
keydown 按下键盘时触发该事件。
keyup 松开键盘时触发该事件。
keypress 只要按下的键并非Ctrl、Alt、Shift和Meta,就接着触发keypress事件(较少用到)。
只要用户一直按键不松开,就会连续触发键盘事件,触发顺序如下:
keydown
keypress
keydown
keypress
(重复以上过程)
keyup
在这里,我们只来了解keydown和keyup就足够了。
我们会将事件绑定到window上,而不是canvas上,因为如果将键盘事件绑定到某个元素上,那么该元素只有在获取到焦点时才会触发键盘事件,而绑定到window上时,我们可以任何时候监听到。
一般来说,我们比较关心键盘上的箭头按钮(上下左右):
function keyEvent(event){
switch (event.keyCode){
case 38:
keybox.innerHTML = '你点击了向上箭头(↑)';
break;
case 40:
keybox.innerHTML = '你点击了向下箭头(↓)';
break;
case 37:
keybox.innerHTML = '你点击了向左箭头(←)';
break;
case 39:
keybox.innerHTML = '你点击了向右箭头(→)';
break;
default:
keybox.innerHTML = '你点击了其他按钮';
};
};
window.addEventListener('keydown',keyEvent,false);
为了便利,我将keydown和keyup事件封装成这样:
window.tool.captureKeyDown = function(params) {
function keyEvent(event) {
params[event.keyCode]();
};
window.addEventListener('keydown', keyEvent, false);
};
window.tool.captureKeyUp = function(params) {
function keyEvent(event) {
params[event.keyCode]();
};
window.addEventListener('keyup', keyEvent, false);
};
需要时只需如下调用:
function keyLeft(){
keybox.innerHTML = '你点击了向左箭头(←)';
};
function keyRight(){
keybox.innerHTML = '你点击了向右箭头(→)';
};
window.tool.captureKeyEvent({"37":keyLeft,"39":keyRight});
传入一个键值对形式的对象,键名是键码,键值是调用函数。
实例(先点击下面,让其获取到焦点):
在后面会有个附录,有完整的键码值对应表。不过,我们不需要去死记硬背,你可以使用到再去查或者使用插件 keycode.js(可到这里下载:https://github.com/lamberta/html5-animation):
<script src="keycode.js"></script>
<script>
function keyEvent(event){
switch (event.keyCode){
case keycode.UP:
keybox.innerHTML = '你点击了向上箭头(↑)';
break;
};
};
window.addEventListener('keydown',keyEvent,false);
</script>
其实keycode.js里定义了一个全局变量keycode,然后以键值对的形式定义键名和键名值。
总结
用户交互在游戏动画中是很重要的一步,所以掌握用户交互的各种事件是必须的,而且特别强调一点是,要学会制造轮子,避免重复的编写相同的代码,不过,初学者建议多敲 。
如有问题,欢迎指正!
附录:
更多建议: