沒有用戶交互的動(dòng)畫就跟電視上的動(dòng)畫片一樣,不管誰看,都是一個(gè)樣,千年不變。顯然,這不是我們想要的,很多時(shí)候,我們需要用戶參與進(jìn)來,這樣才能產(chǎn)生豐富的動(dòng)畫效果,這就是專門用一章來了解用戶交互的原因。
function MClick(event){
console.log('鼠標(biāo)點(diǎn)擊了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對(duì)象*/
function getPoint(event){
event = event || window.event; /*為了兼容IE*/
/*將當(dāng)前的鼠標(biāo)坐標(biāo)值減去元素的偏移位置,返回鼠標(biāo)相對(duì)于element的坐標(biāo)值*/
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);
};
/*回調(diào)函數(shù)會(huì)傳入一個(gè)event對(duì)象,event.point中包含了x和y屬性,分別對(duì)應(yīng)鼠標(biāo)相對(duì)element的X坐標(biāo)和Y坐標(biāo),函數(shù)內(nèi)的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;
/*清除整個(gè)canvas畫布*/
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.fillStyle = 'red';
ctx.beginPath();
/*繪制一個(gè)跟隨鼠標(biāo)的圓*/
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元素,后面是傳入三個(gè)函數(shù),分別對(duì)應(yīng)mousedown、mousemove和mouseup事件的事件處理函數(shù)*/
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對(duì)象*/
function getPoint(event){
event = event || window.event;
var touchEvent = event.changedTouches[0];
/*將當(dāng)前的鼠標(biāo)坐標(biāo)值減去元素的偏移位置,返回鼠標(biāo)相對(duì)于element的坐標(biāo)值*/
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對(duì)象*/
function getPoint(event) {
/*將當(dāng)前的觸摸點(diǎn)坐標(biāo)值減去元素的偏移位置,返回觸摸點(diǎn)相對(duì)于element的坐標(biāo)值*/ 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);
};
在上面的代碼中,我們先檢測是移動(dòng)還是PC('ontouchend' in document),然后將布爾值傳給變量 isTouch ,然后定義使用mouse事件還是touch事件,獲取坐標(biāo)點(diǎn)時(shí),也是根據(jù) isTouch的值來絕對(duì)直接用 event還是用 event.changedTouches[0] 。
實(shí)例(移動(dòng)PC都可以使用):
4、鍵盤事件
鍵盤事件只有三個(gè):
keydown 按下鍵盤時(shí)觸發(fā)該事件。
keyup 松開鍵盤時(shí)觸發(fā)該事件。
keypress 只要按下的鍵并非Ctrl、Alt、Shift和Meta,就接著觸發(fā)keypress事件(較少用到)。
只要用戶一直按鍵不松開,就會(huì)連續(xù)觸發(fā)鍵盤事件,觸發(fā)順序如下:
keydown
keypress
keydown
keypress
(重復(fù)以上過程)
keyup
在這里,我們只來了解keydown和keyup就足夠了。
我們會(huì)將事件綁定到window上,而不是canvas上,因?yàn)槿绻麑㈡I盤事件綁定到某個(gè)元素上,那么該元素只有在獲取到焦點(diǎn)時(shí)才會(huì)觸發(fā)鍵盤事件,而綁定到window上時(shí),我們可以任何時(shí)候監(jiān)聽到。
一般來說,我們比較關(guān)心鍵盤上的箭頭按鈕(上下左右):
function keyEvent(event){
switch (event.keyCode){
case 38:
keybox.innerHTML = '你點(diǎn)擊了向上箭頭(↑)';
break;
case 40:
keybox.innerHTML = '你點(diǎn)擊了向下箭頭(↓)';
break;
case 37:
keybox.innerHTML = '你點(diǎn)擊了向左箭頭(←)';
break;
case 39:
keybox.innerHTML = '你點(diǎn)擊了向右箭頭(→)';
break;
default:
keybox.innerHTML = '你點(diǎn)擊了其他按鈕';
};
};
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);
};
需要時(shí)只需如下調(diào)用:
function keyLeft(){
keybox.innerHTML = '你點(diǎn)擊了向左箭頭(←)';
};
function keyRight(){
keybox.innerHTML = '你點(diǎn)擊了向右箭頭(→)';
};
window.tool.captureKeyEvent({"37":keyLeft,"39":keyRight});
傳入一個(gè)鍵值對(duì)形式的對(duì)象,鍵名是鍵碼,鍵值是調(diào)用函數(shù)。
實(shí)例(先點(diǎn)擊下面,讓其獲取到焦點(diǎn)):
在后面會(huì)有個(gè)附錄,有完整的鍵碼值對(duì)應(yīng)表。不過,我們不需要去死記硬背,你可以使用到再去查或者使用插件 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 = '你點(diǎn)擊了向上箭頭(↑)';
break;
};
};
window.addEventListener('keydown',keyEvent,false);
</script>
其實(shí)keycode.js里定義了一個(gè)全局變量keycode,然后以鍵值對(duì)的形式定義鍵名和鍵名值。
總結(jié)
用戶交互在游戲動(dòng)畫中是很重要的一步,所以掌握用戶交互的各種事件是必須的,而且特別強(qiáng)調(diào)一點(diǎn)是,要學(xué)會(huì)制造輪子,避免重復(fù)的編寫相同的代碼,不過,初學(xué)者建議多敲 。
如有問題,歡迎指正!
附錄:
更多建議: