Emscripten canvas + jQuery - 切换焦点

Posted

技术标签:

【中文标题】Emscripten canvas + jQuery - 切换焦点【英文标题】:Emscripten canvas + jQuery - toggle focus 【发布时间】:2017-08-29 10:30:48 【问题描述】:

我有一个 html 页面,大致将 30% - 70% 分成两个垂直列。左列包含聊天提要(通过 Node 和 Socket.io 处理),右列包含 emscripten 生成的canvas(ID 为canvas)。画布包含一个基本的 3D 世界,用户可以使用标准的第一人称控件(WASD 用于移动,鼠标用于“查看”)进行导航。

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

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

这让我可以手动关注聊天框,输入消息并提交。

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

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

名义上这会将焦点返回到画布,但鼠标和键盘移动不起作用。奇怪的是,单击选项卡/浏览器窗口然后进入画布似乎工作 - 焦点返回到画布,我可以再次导航。手动调用 $(window).blur().focus() 是不行的。

有谁知道一旦发送了聊天消息,如何将焦点强制回到画布上?

-- 更新--

我在画布后面添加了一个文本输入字段(ID 为hiddenField),并且我正在使用 preRun 函数将画布的关键事件分配给该字段(画布在某些情况下无法始终如一地工作原因)。

这工作正常直到用户点击画布 - 例如,进入聊天字段 - 然后画布停止响应任何键盘或鼠标输入,即使我触发焦点回到hiddenField(并且可以看到它正在获取它)。

似乎在页面上执行任何操作与 emscripten 的聚焦行为(我相信与窗口对象绑定)冲突,并阻止画布重新获得焦点。

肯定有某种方法可以让 emscripten 画布与其他 HTML 元素一起存在吗?

【问题讨论】:

【参考方案1】:

您需要通过添加tabindex="0" 属性使canvas 对象可聚焦。

那么应该可以正常触发焦点事件了:

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

【讨论】:

【参考方案2】:

我能找到的最佳方法——事实上,让应用程序的各个方面(聊天和 3D 世界)正常工作的唯一方法——是将 emscripten 画布嵌入到 iframe并在必要时使用跨框架函数调用来触发动作。

Page
    - chat
    - iframe
        -- emscripten-generated page

这不是我的首选解决方案,但它是我设法开始工作的唯一一个。

【讨论】:

【参考方案3】:

编辑:

通过CodePen查看完整演示(包括指向.js资源的链接)

结构:

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

必须在画布元素上设置tabindex(如luke 和described on MDN 所述),通过javascript 的内置Document 接口附加全局事件侦听器,然后调用@ 987654329@ 以确保画布返回到其默认状态,由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 键的行为。

【讨论】:

以上是关于Emscripten canvas + jQuery - 切换焦点的主要内容,如果未能解决你的问题,请参考以下文章

在 html5 画布上通过 emscripten 使用 WebGL

Emscripten教程之Emscripten的运行时环境

Emscripten教程之Emscripten的运行时环境

Emscripten教程之优化你的代码

Emscripten教程之入门指导

是否可以像现在一样轻松编译 Emscripten,但没有控制台和 emscripten 徽标?