问题背景
在开发 Web 应用时,尤其是集成了 Unity WebGL 内容的页面,常会遇到一个棘手的问题:当 Unity WebGL 渲染内容嵌入到一个 Tab 中时,切换 Tab 后画面会变黑,直到用户点击黑屏区域,才会恢复显示。
这通常是因为 Unity 渲染在 Tab 切换时被暂停或未能获得焦点所致。浏览器为了性能优化,会在页面不可见或失去焦点时暂停 Canvas 渲染循环。
解决思路
要解决这个问题,关键是确保每次切换到包含 Unity WebGL 的 Tab 时,Unity 渲染能够继续运行。核心思路是通过 Layui 框架提供的事件监听 Tab 切换,获取当前激活的 Tab,然后强制 Unity canvas 元素重新获得焦点。
具体实现
Layui 框架中的 element 模块提供了 tab 事件,可以用于监听 Tab 的切换。当 Tab 切换时,可以通过事件获取到当前活动 Tab 的索引值,并确定哪个 Tab 中包含 Unity WebGL 内容。
Unity WebGL 通常嵌入在一个 iframe 中,iframe 内部包含 Unity 渲染的 canvas 元素。在 Tab 切换时,我们需要访问该 iframe,并获取其中的 Unity canvas 元素,调用 JavaScript 的 focus() 方法即可。
layui.use(['element'], function() {
var element = layui.element;
// 监听 Tab 切换事件,注意这里的 'xbs_tab' 需替换为你的实际 Tab name
element.on('tab(xbs_tab)', function(data) {
var activeTabId = data.index;
// 获取当前选中的 Tab 对应的 iframe 容器
var iframe = $('.x-iframe').eq(activeTabId);
// 尝试获取 iframe 内部的 Unity canvas 元素
// 注意:iframe 必须同源,否则无法访问 contents()
var unityCanvas = iframe.contents().find('#unity-canvas')[0];
if (unityCanvas) {
unityCanvas.focus(); // 强制获取焦点,唤醒渲染
}
});
});
代码逻辑拆解
这段代码主要做了三件事:
- 加载模块:使用
layui.use加载element模块,这是处理 Layui 组件交互的基础。 - 绑定事件:通过 监听特定名称的 Tab 切换事件。回调函数会接收到当前 Tab 的数据对象,其中包含索引信息。


