在游戏中按空格键会进行角色拍摄,当显示确认框时按空格键会使此框消失,按高分形式按空格键将在输入框中添加空格。在此示例中,同一个键有几个事件,但一次只触发一个。
是否有一般(或特定于Javascript)方法或编程方式将事件添加到某个键,因此它们只在某些情况下执行?
当然可以这样做:
var inGame = true|false;
var inConfirmationBox = true|false;
function spaceBarHandler(){
if(inGame){ /*shoot*/}
else if(inConfirmationBox){ /*remove box*/}
}
document.onkeydown = function(){ /* call space bar handler if space bar was pressed */ };
但这是一种非常令人困惑的编程方式,因为特定的动作在空格键处理函数中混合在一起,这使维护变得困难。
处理一个键的多个事件的最佳方法是什么,这样只会在某些情况下触发这些事件?
答案 0 :(得分:4)
函数是javascript中的第一类对象,这使它们非常强大。因此,您的问题可以非常优雅地解决。
// the whole thing can be encapsulated
// into an object actually
function spaceBarHandler() {
var state = spaceBarHandler.state;
var actions = spaceBarHandler.actions;
// execute function if exists
if (actions[state]) {
actions[state]();
}
}
// spaceBar actions
spaceBarHandler.actions = {
shoot: function() {
// bang bang
},
removeBox: function() {
// do it...
}
};
// change current state from outside
// we are in the game
spaceBarHandler.state = "shoot";
// change current state from outside
// confirmation box is shown
spaceBarHandler.state = "removeBox";
所有这些案例都将由一个函数处理。如果要扩展另一个案例,只需向actions对象添加另一个函数即可。注意如何将整个事物封装到一个对象中。
答案 1 :(得分:0)
将事件监听器附加到单个元素而不是整个文档。
document.getElementById('highscore').onkeypress = function(keyEvent) {
if (is_spacebar(keyEvent)) //Do something...
};
document.getElementById('game').onkeypress = function(keyEvent) {
if (is_spacebar(keyEvent)) //Do something else...
};
这是一个简单的例子。您可能必须处理事件冒泡,当使用addEventListener()将函数附加到事件时,可以控制事件冒泡。鉴于涉及此问题的浏览器(IE)兼容性问题,应该使用一些JS库来处理事件。
答案 2 :(得分:0)
有几种方法,通常涉及IE的“特殊”事件模型的代码分支。
一种方法是停止从按钮冒泡到文档密钥处理程序进一步处理的按键:
confirmationbox.onkeydown = function(event) {
if (event === undefined) event = window.event;
// do something with event.keyCode
if ('stopPropagation' in event) // standards browsers
event.stopPropagation();
else if ('cancelBubble' in event) // IE before version 9
event.cancelBubble = true;
};
document.onkeydown = ... // will not be called for keydowns inside confirmationbox
另一种方法是检查事件目标元素以查看它是否在框中:
document.onkeydown = function(event) {
if (event === undefined) event = window.event;
var target = 'target' in event ? event.target : event.srcElement; // srcElement is for IE<9
if (target === containerbox || isDescendantOf(target, containerbox) {
// do containerbox stuff
} else {
// do other stuff
}
};
function isDescendantOf(element, ancestor) {
while (element = element.parentNode)
if (element === ancestor)
return true;
return false;
}
答案 3 :(得分:0)
您可以根据需要添加和删除事件侦听器。
让我们假设你正在使用一个javascript框架(如果你不是,那么你可能应该考虑像这样的游戏中涉及的JS代码量)。
使用PrototypeJS:
比赛开始时,
document.observe("keydown",shootHandler());
创建消息框时
function createBox(text) {
...snip
document.observe("keydown",closeBox());
document.fire("game:pause");
}
,例如
var paused = false;
function shoothandler() {
if (!paused) {
alert("pew! pew!");
}
}
function closeBox() {
$('messagebox').remove();
document.fire("game:unpaused");
document.stopObserving("keydown",closeBox());
}
document.observe("game:paused", function() { paused = true;});
document.observe("game:unpaused", function() { paused = false;});
document.observe("game:over", function() { document.stopObserving("keydown",shootHandler());});
我没有包括高分屏幕,但理论是一样的。
如您所见,我还使用自定义事件来通知暂停状态。同样的事件也可以通过界面中的puase按钮等来触发......