Emscripten canvas + jQuery - переключить фокус

У меня есть HTML-страница, грубо разделенная на 30% - 70% на две вертикальные столбцы. В левом столбце содержится чат-канал (обрабатывается через Node и Socket.io), а правый столбец содержит генерируемый emscripten canvas (с идентификатором canvas). Холст содержит базовый 3D-мир, который пользователь может перемещать с помощью стандартных элементов управления от первого лица (WASD для перемещения, мыши для "просмотра" ).

По умолчанию холст поглощает все события клавиатуры. Я исправил это с помощью следующего кода в процедуре инициализации холста:

Module.preRun.push(function () {
    ENV.SDL_EMSCRIPTEN_KEYBOARD_ELEMENT = "#canvas";
});

Это позволяет мне вручную сосредоточиться на окне чата, ввести сообщение и отправить его.

Проблема, с которой я сталкиваюсь, заключается в том, что после отправки сообщения чата я пытаюсь вернуть фокус на холст с помощью следующего кода (чтобы игроки могли перемещаться по 3D-миру с помощью WASD):

 $('#canvas').focus();

Это номинально возвращает фокус на холст, но движение мыши и клавиатуры не работает. Странно, щелкнув окно вкладки/браузера, а затем в холст, похоже, работает - фокус возвращается на холст, и я могу перемещаться еще раз. Вручную вызов $(window).blur().focus() не выполняет трюк.

Кто-нибудь знает, как заставить фокус вернуться к холсту после отправки сообщения чата?

- ОБНОВЛЕНИЕ -

Я добавил текстовое поле ввода (с идентификатором hiddenField) за холстом, и я использую функцию preRun для назначения ключевых событий для холста в это поле (холст не работал последовательно для некоторых причина).

Это прекрасно работает, пока пользователь не закроет холст, например, в поле чата, после чего холст перестает отвечать на любой ввод клавиатуры или мыши, хотя я запускаю фокус обратно на hiddenField (и может видеть, что он ее получает).

Кажется, что что-либо на странице конфликтует с тем, что фокусное поведение emscripten (я полагаю, привязано к объекту окна) и не позволяет холсту восстановить фокус.

Конечно, есть способ сгладить холст emscripten, чтобы жить вместе с другими элементами HTML?

Ответ 1

Лучший подход, который я смог найти в этом - действительно, единственный способ правильно работать с отдельными аспектами приложения (чат и мир 3D) - это внедрить холст emscripten в iframe и при необходимости использовать вызовы функций межкадровой функции для запуска действий.

Page
    - chat
    - iframe
        -- emscripten-generated page

Это не мой первый выбор решения, но он единственный, с которым мне удалось работать.

Ответ 2

Вам нужно сделать объект canvas ориентированным, добавив атрибут tabindex="0".

Тогда должно быть возможно правильно запустить событие фокусировки:

document.querySelector("#canvas").focus()

Ответ 3

EDIT:

Посмотреть полную демонстрацию через CodePen (включает ссылки на ресурсы .js)

Состав:

Page
    - emscripten-generated-page
       - loop
    - chat
    - script to handle global key input handlers

Вы должны установить tabindex в элемент холста (как отмечено luke и описанный в MDN), присоедините глобальные прослушиватели событий через встроенный интерфейс Document через JavaScripts, а затем вызовите .triggerHandler(), чтобы гарантировать, что canvas возвращает его состояние по умолчанию, управляемое click:

var chatInputField = $("#message-input");
var canvas = $("#canvas");


canvas.on("click", function(e){
  return document.addEventListener("keyup", game.toggleKeys);
});

chatInputField.on("focusin", function(e) {
    $('#canvas').attr('tabindex', 0);
    return document.removeEventListener("keyup", game.toggleKeys, false);
});

chatInputField.on("focusout", function(e) {
    $("#canvas").triggerHandler('click');
    chatInputField.attr('tabindex', 0);
});

Ive проверил это, он работает. Heres my app.js файл для управления вводом ключа (см. Строку 297).

https://gist.github.com/shagamemnon/585df8dd215a949b839f8b02199af31b

Предостережение: вы должны явно определить поведение ключа tab внутри холста игры.