Что лучший способ состоит в том, чтобы обработать несколько ключевых событий в JavaScript?

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

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

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

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

10
задан Harmen 29 June 2010 в 18:11
поделиться

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";

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

4
ответ дан 4 December 2019 в 04:01
поделиться

Есть несколько способов, обычно связанных с ветвлением кода для «специальной» модели событий 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
ответ дан 4 December 2019 в 04:01
поделиться

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

предположим, что вы используете фреймворк 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
ответ дан 4 December 2019 в 04:01
поделиться

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

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-библиотеку.

0
ответ дан 4 December 2019 в 04:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: