2017-08-29 101 views
11

我有一个HTML页面,粗略地将30%-70%划分为两个垂直列。左栏包含一个聊天源(通过Node和Socket.io处理),右列包含一个emscripten生成的canvas(ID为canvas)。画布包含一个基本的3D世界,用户可以使用标准的第一人称控件(WASD移动,鼠标移动到“外观”)进行导航。Emscripten canvas + jQuery - 切换焦点

默认情况下,画布吞下所有键盘事件。我与画布初始化过程在下面的代码解决了这个问题:

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

这让我手动对焦聊天框中,键入消息,并提交。

我遇到的问题是,一旦聊天消息已提交,我试着用下面的代码焦点返回到画布(允许玩家使用导航WASD 3D世界):

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

名义上将焦点返回到画布,但鼠标和键盘移动不起作用。奇怪的是,单击标签页/浏览器窗口,然后进入画布似乎工作 - 焦点返回到画布,我可以再次导航。手动拨打$(window).blur().focus()并不能解决问题。

有没有人知道如何强制回到画布一旦聊天消息已发送?

- 更新 -

我在画布背后添加了一个文本输入框(与hiddenField的ID)和我正在使用预电泳功能分配关键事件为画布到字段(由于某种原因,画布不能始终如一地工作)。例如,在聊天字段 - -

直到用户点击了画布工作正常于是画布停止响应任何键盘或鼠标输入,即使我触发聚焦放回hiddenField(和可以看到它得到它)。

看起来这个页面上的任何东西与emscripten的聚焦行为(我认为绑定到窗口对象)冲突,并阻止画布重新获得焦点。

肯定有一些方法可以让emscripten画布与其他HTML元素一起生活吗?

回答

6

我已经能够找到这一点的最好办法 - 实际上,获取应用程序的独立方面的唯一途径(聊天& 3D世界)正常工作 - 已嵌入在iframe的emscripten帆布必要时使用跨帧函数调用来触发操作。

Page 
    - chat 
    - iframe 
     -- emscripten-generated page 

这不是我的解决方案的第一选择,但它是我唯一能成功工作的人。

2

您需要通过添加tabindex="0"属性使canvas对象成为焦点。

然后,它应该能够正确地触发焦点事件:

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

编辑:通过CodePen

查看完整的演示(包括链接到.js资源)

结构:

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

必须设置tabindex canvas元素(如lukedescribed on MDN说明),通过连接全球的事件侦听器的JavaScript的内置Document接口,然后调用.triggerHandler()确保画布返回到它的默认状态,管辖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); 
}); 

我测试过了,它的工作原理。这是我的app.js文件,用于管理密钥输入(请参阅第297行)。

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

一个警告:你必须明确定义游戏画布内的tab键的行为。