Каков наилучший способ обработки нескольких ключевых событий в Javascript? - PullRequest
10 голосов
/ 29 июня 2010

Нажатие клавиши «пробел» в игре приведет к стрельбе персонажа, нажатие клавиши «пробел» при появлении окна подтверждения приведет к исчезновению этого поля, а нажатие клавиши пробела в форме рекордов добавит пробел в поле ввода.В этом примере есть несколько событий для одного и того же ключа, но одновременно запускается только одно.

Существует ли общий (или специфичный для 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 */ };

Но это очень запутанный способ программирования, поскольку конкретные действия смешиваются вместе вфункция обработчика пробела, которая усложняет обслуживание.

Каков наилучший способ обработки нескольких событий для одной клавиши, чтобы эти события возникали только при определенных обстоятельствах?

Ответы [ 4 ]

4 голосов
/ 29 июня 2010

Функции являются первоклассными объектами в 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";

Все эти случаи будут обрабатываться одной функцией. Если вы хотите расширить другой случай, вы просто добавляете другую функцию к объекту действий. Обратите внимание, как все это заключено в один объект.

0 голосов
/ 29 июня 2010

вместо этого вы можете добавлять и удалять прослушиватель событий по мере необходимости.

давайте предположим, что вы используете фреймворк 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 в интерфейсе и т. Д.

0 голосов
/ 29 июня 2010

Существует несколько способов, обычно включающих ветвление кода для «особой» модели событий 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;
}
0 голосов
/ 29 июня 2010

Прикрепите прослушиватели событий к отдельным элементам вместо всего документа.

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 для обработки событий.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...