2017-08-29 56 views
11

Mam stronę HTML z grubsza podzielone 30% - 70% na dwie pionowe kolumny. W lewej kolumnie znajduje się kanał czatu (obsługiwany przez węzły i Socket.io), a prawa kolumna zawiera wygenerowany emscripten canvas (z identyfikatorem canvas). Płótno zawiera podstawowy świat 3D, w którym użytkownik może nawigować za pomocą standardowych elementów sterujących pierwszej osoby (WASD dla ruchu, mysz dla "wyglądu").Emscripten canvas + jQuery - przełączanie ostrości

Domyślnie płótno pochłania wszystkie zdarzenia na klawiaturze. Naprawiłem to z następującego kodu w procedurze płótno inicjalizacji:

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

To pozwala mi skupić się ręcznie w oknie czatu, wpisać wiadomość i wysłać.

Kwestia biegnę na to, że gdy wiadomość czat został złożony, staram i powrotu ostrości na płótnie z następującego kodu (aby umożliwić graczom poruszanie się po świecie 3D z WASD):

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

Powoduje nominalnie powrót do obrazu, ale ruch myszy i klawiatury nie działa. Co dziwne, kliknięcie okna zakładki/przeglądarki, a następnie na płótno, wydaje się działać - ostrość jest zwracana do obszaru roboczego i mogę nawigować jeszcze raz. Ręczne wywoływanie $(window).blur().focus() nie działa.

Czy ktoś wie, jak zmusić fokus do powrotu do obszaru roboczego po wysłaniu wiadomości na czacie?

- AKTUALIZACJA -

Dodałem pole wprowadzania tekstu (z ID hiddenField) za płótno i używam funkcji wstępnej pracy przypisać kluczowe wydarzenia na płótnie, które pole (płótno nie działało konsekwentnie z jakiegoś powodu).

Działa to dobrze użytkownik kliknie poza płótno - na przykład w polu czatu - czym płótno przestaje reagować na jakiekolwiek wejścia klawiatury lub myszki, chociaż ja wyzwalanie ostrość z powrotem na hiddenField (i widać, że to robi).

Wygląda na to, że wykonanie niczego na stronie jest w konflikcie z zachowaniem skupiającym emscriptena (powiązanym z obiektem okna, jak sądzę) i zapobiega przywróceniu przez płótno ostrości.

Z pewnością istnieje sposób na zachowanie płótna emscripten, aby mógł łączyć się z innymi elementami HTML?

Odpowiedz

6

Najlepszym podejściem udało mi się znaleźć na to - w istocie, jedynym sposobem, aby uzyskać odrębne aspekty stosowania (czat & świecie 3D) działa poprawnie - nie było osadzić płótno emscripten w iframe i użyj wywołań funkcji międzymiastowych, gdy jest to konieczne, aby uruchomić akcje.

Page 
    - chat 
    - iframe 
     -- emscripten-generated page 

To nie jest mój pierwszy wybór rozwiązania, ale to jedyny, który udało mi się uzyskać.

2

Należy dokonać ogniskowania obiektu canvas, dodając atrybut tabindex="0".

Wtedy powinno być możliwe, aby wywołać zdarzenie ostrości odpowiednio:

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

EDIT:

Zobacz pełny demo poprzez CodePen (zawiera linki do .js zasobów)

strukturę:

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

Ty koniecznością ustawić tabindex na elemencie canvas (jak zauważył luke i described on MDN), dołączyć detektory zdarzeń globalnych poprzez JavaScript wbudowanego w Document interfejsu, a następnie zadzwonić .triggerHandler() aby zapewnić, że zyski płótno na to stan domyślny, regulowane 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); 
}); 

Testowałem to, to działa. Oto mój plik app.js do zarządzania wprowadzaniem klucza (patrz wiersz 297).

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

zastrzeżenie: ty koniecznością jednoznacznie określić zachowanie klucza wewnątrz płótnie gry tab.