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
внутри холста игры.