如何在 web worker 中使用 PixiJS
How to use PixiJS in web worker
我需要使用 PixiJS 在 canvas 中显示一个相当复杂的二维形状,为此我想在单独的线程(网络工作者)中创建和定义所有图形元素,以免阻塞UI 的其余部分。
问题是当我像这样在 web worker 文件中导入 PixiJS 时
importScripts('https://cdnjs.cloudflare.com/ajax/libs/pixi.js/4.5.2/pixi.js');
它给我一个错误,因为它访问 DOM 元素(如 window 和文档),这在网络工作者中是不允许的。我该如何解决?
这是错误:
Uncaught ReferenceError: window is not defined
at Object.179../Math.sign (Object.assign.js:3)
at s (_prelude.js:1)
at _prelude.js:1
at Object.<anonymous> (WebGLPrepare.js:101)
at Object.187../accessibility (index.js:44)
at s (_prelude.js:1)
at e (_prelude.js:1)
at _prelude.js:1
at _prelude.js:1
at _prelude.js:1
嗯,我想你不能。 Webworker 有自己的 DedicatedWorkerGlobalScope,无法访问 DOM、window 等。如果你有繁重的计算,例如计算动画,你所能做的就是让 webworker 做数字运算和主线程进行渲染。
Worker和主线程不能共享对象。即使以下解释在技术上不是 100% 正确,您可以想象如果您:
var obj = { a: { b: 100 } };
worker.postMessage(obj);
会更像:
//really dirty object clone here
worker.postMessage(JSON.parse(JSON.stringify(obj)));
我想指出的是,您不能与 worker 共享对象,反之亦然。
在此处找到技术上正确的解释:
Philipp 的回答是正确的,我只是想从游戏和网络工作者的角度进一步阐述一下。
根据我的经验,通常很难在游戏中利用网络工作者。特别是如果你使用一个库来处理 canvas / webGL,因为无论如何这都会处理大部分的数字。正如 philipp 提到的,网络工作者是为数字运算而设计的。在 web worker 和主线程之间传递数据是非常昂贵的,所以传递数据并对它们进行微小的操作,不会有好处。
在没有提供直接 link 的情况下,我很久以前就已经读到一些游戏引擎(我认为是构造)使用网络工作者作为他们的寻路模块。所以与直接图形处理无关,而是数值运算。
还有一个关于在 web worker 上下文中使用 canvases 的可能性的提议,所以这显然也是其他人的问题。如果我没记错的话,我相信是这样的:https://developer.mozilla.org/fi/docs/Web/API/OffscreenCanvas
您可以在您的 Web Worker 中包含 PixiJS,尽管您不能执行图形操作。
虽然其他两个答案在技术上是正确的,但在不实际渲染图形的情况下将 Pixi 的代码包含在您的 Worker 范围内是合法的用例。一个例子是使用 Pixi 的 Point
和 Rectangle
类。就我而言,我编写了几个模块,这些模块依赖于 Pixi 导出的定义并基于它们执行大量计算。
您遇到的错误是因为 Pixi 依赖全局变量 window
和 document
来定义一些与图形相关的常量。为了让 Pixi 完成加载,您可以使用与 Pixi 使用的方法同名的空方法为 window
和 document
提供模拟值。
例如,在使用 PixiJS 4.8.6 时,以下代码对我有效:
window = self
document = {
createElement () {
return {
getContext () {
return {
fillRect () {},
drawImage () {},
getImageData () {},
}
},
}
},
}
importScripts('pixi-4-8-6.js');
/* Web Worker code follows */
// ...
根据 Pixi 的版本,您可能需要调整此样板文件。另一种方法是尝试为无头浏览器模拟 document
和 Canvas
的那些软件包之一。我还没有尝试过,因为上面的代码运行得很好。
Pixi 5 最近问世,它可能彻底改变了这一点。我浏览了代码,看起来他们删除了导致问题的常量定义,所以这个新版本也有可能开箱即用。我知道他们一直在研究让人们更轻松地使用 Workers,并且他们一直在探索 OffscreenCanvas,就像 Hachi 所说的那样。
pixi 团队正在努力添加 headless 环境支持,例如 web worker;见 https://github.com/pixijs/pixijs/issues/7123
我需要使用 PixiJS 在 canvas 中显示一个相当复杂的二维形状,为此我想在单独的线程(网络工作者)中创建和定义所有图形元素,以免阻塞UI 的其余部分。
问题是当我像这样在 web worker 文件中导入 PixiJS 时
importScripts('https://cdnjs.cloudflare.com/ajax/libs/pixi.js/4.5.2/pixi.js');
它给我一个错误,因为它访问 DOM 元素(如 window 和文档),这在网络工作者中是不允许的。我该如何解决?
这是错误:
Uncaught ReferenceError: window is not defined
at Object.179../Math.sign (Object.assign.js:3)
at s (_prelude.js:1)
at _prelude.js:1
at Object.<anonymous> (WebGLPrepare.js:101)
at Object.187../accessibility (index.js:44)
at s (_prelude.js:1)
at e (_prelude.js:1)
at _prelude.js:1
at _prelude.js:1
at _prelude.js:1
嗯,我想你不能。 Webworker 有自己的 DedicatedWorkerGlobalScope,无法访问 DOM、window 等。如果你有繁重的计算,例如计算动画,你所能做的就是让 webworker 做数字运算和主线程进行渲染。
Worker和主线程不能共享对象。即使以下解释在技术上不是 100% 正确,您可以想象如果您:
var obj = { a: { b: 100 } };
worker.postMessage(obj);
会更像:
//really dirty object clone here
worker.postMessage(JSON.parse(JSON.stringify(obj)));
我想指出的是,您不能与 worker 共享对象,反之亦然。
在此处找到技术上正确的解释:
Philipp 的回答是正确的,我只是想从游戏和网络工作者的角度进一步阐述一下。
根据我的经验,通常很难在游戏中利用网络工作者。特别是如果你使用一个库来处理 canvas / webGL,因为无论如何这都会处理大部分的数字。正如 philipp 提到的,网络工作者是为数字运算而设计的。在 web worker 和主线程之间传递数据是非常昂贵的,所以传递数据并对它们进行微小的操作,不会有好处。
在没有提供直接 link 的情况下,我很久以前就已经读到一些游戏引擎(我认为是构造)使用网络工作者作为他们的寻路模块。所以与直接图形处理无关,而是数值运算。
还有一个关于在 web worker 上下文中使用 canvases 的可能性的提议,所以这显然也是其他人的问题。如果我没记错的话,我相信是这样的:https://developer.mozilla.org/fi/docs/Web/API/OffscreenCanvas
您可以在您的 Web Worker 中包含 PixiJS,尽管您不能执行图形操作。
虽然其他两个答案在技术上是正确的,但在不实际渲染图形的情况下将 Pixi 的代码包含在您的 Worker 范围内是合法的用例。一个例子是使用 Pixi 的 Point
和 Rectangle
类。就我而言,我编写了几个模块,这些模块依赖于 Pixi 导出的定义并基于它们执行大量计算。
您遇到的错误是因为 Pixi 依赖全局变量 window
和 document
来定义一些与图形相关的常量。为了让 Pixi 完成加载,您可以使用与 Pixi 使用的方法同名的空方法为 window
和 document
提供模拟值。
例如,在使用 PixiJS 4.8.6 时,以下代码对我有效:
window = self
document = {
createElement () {
return {
getContext () {
return {
fillRect () {},
drawImage () {},
getImageData () {},
}
},
}
},
}
importScripts('pixi-4-8-6.js');
/* Web Worker code follows */
// ...
根据 Pixi 的版本,您可能需要调整此样板文件。另一种方法是尝试为无头浏览器模拟 document
和 Canvas
的那些软件包之一。我还没有尝试过,因为上面的代码运行得很好。
Pixi 5 最近问世,它可能彻底改变了这一点。我浏览了代码,看起来他们删除了导致问题的常量定义,所以这个新版本也有可能开箱即用。我知道他们一直在研究让人们更轻松地使用 Workers,并且他们一直在探索 OffscreenCanvas,就像 Hachi 所说的那样。
pixi 团队正在努力添加 headless 环境支持,例如 web worker;见 https://github.com/pixijs/pixijs/issues/7123