如何在 PixiJS 中更优雅地处理 WebGL CONTEXT_LOST_WEBGL 错误?
How to handle WebGL CONTEXT_LOST_WEBGL errors more gracefully in PixiJS?
我有一个使用 PixiJS 的数据可视化库的 React 应用程序。
我偶尔会在 Chrome 中遇到令人沮丧的 CONTEXT_LOST_WEBGL
错误,这些错误迫使用户手动重新加载页面,以便(重新)呈现页面。
我不能经常或可靠地重现错误,但我知道它会发生,因为其他人告诉我应用程序偶尔会不显示任何数据。引发此错误的情况似乎非常依赖于上下文,因此很难概括——低功率图形适配器,或同时打开大量选项卡等。
如果最终用户打开了开发者工具控制台 window,则他们只会知道存在 CONTEXT_LOST_WEBGL
错误。否则,网页看起来只是一片空白。
我尝试了以下设置我的 React 应用程序以在 webglcontextlost
事件发生时重新加载 window 而无需用户手动干预:
componentDidMount() {
...
window.addEventListener("webglcontextlost", (e) => { window.location.reload(); });
...
}
我不确定它是否正常工作,即,如果 webglcontextlost
事件正在别处处理。或许我正在尝试订阅错误的事件?
否则,为了更优雅地处理这个问题,有没有办法在原始 Javascript 中或通过第三方库定期测量 WebGL 的可用内存,并使用该测量来代替重新加载页面,当可用内存达到某个可能预测即将发生的 CONTEXT_LOST_WEBGL
错误情况的任意阈值时?
is there a way in raw Javascript to periodically measure available memory for WebGL
没有,就像没有办法测量JavaScript内存
window.addEventListener("webglcontextlost", (e) => { window.location.reload(); });
错了。应该是
someCanvas.addEventListener("webglcontextlost", (e) => { window.location.reload(); });
每个 canvas 都可以单独失去其上下文。大多数浏览器一次只允许 8 到 16 个 WebGL 上下文。一旦达到限制 canvases 就开始失去他们的上下文。
至于优雅地恢复,需要做很多工作。基本上你需要重新创建所有 WebGL 资源,这意味着你需要构建你的代码,这样才有可能。将应用程序的所有状态与与 WebGL 相关的内容(或 pixi.js)分开,当您收到上下文丢失事件时,防止默认并重新创建所有 WebGL 内容
let gl;
someCanvas.addEventListener("webglcontextlost", (e) => {
e.preventDefault(); // allows the context to be restored
});
someCanvas.addEventListener("webglcontextrestored", (e) => {
initWebGL(gl);
});
gl = someCanvas.getContext('webgl');
initWebGL(gl);
请注意,pixi.js 本身可能会或可能不会被设计为处理上下文丢失
当 WebGL 上下文丢失时,以下代码帮助重新启动了我的 Pixijs Web 应用程序:
addCanvasWebGLContextLossEventListener = () => {
const canvases = document.getElementsByTagName("canvas");
if (canvases.length === 1) {
const canvas = canvases[0];
canvas.addEventListener('webglcontextlost', (event) => {
window.location.reload();
});
}
}
removeCanvasWebGLContextLossEventListener = () => {
const canvases = document.getElementsByTagName("canvas");
if (canvases.length === 1) {
const canvas = canvases[0];
canvas.removeEventListener('webglcontextlost');
}
}
对于具有多个 canvas 的其他应用程序,需要进行一些调整以添加其他侦听器。
以下代码帮助我模拟了上下文丢失的情况(并通过 webglcontextlost
事件从中恢复):
simulateWebGLContextLoss = () => {
//
// simulate loss of WebGL context, for the purposes
// of improving user experience when the browser is
// overwhelmed
//
const canvases = document.getElementsByTagName("canvas");
if (canvases.length === 1) {
setTimeout(() => {
const canvas = canvases[0];
const webgl2Context = canvas.getContext("webgl2", {});
if (webgl2Context) {
console.log(`losing webgl2 context...`);
webgl2Context.getExtension('WEBGL_lose_context').loseContext();
}
else {
const webglContext = canvas.getContext("webgl", {});
if (webglContext) {
console.log(`losing webgl context...`);
webglContext.getExtension('WEBGL_lose_context').loseContext();
}
}
}, 5000);
}
}
对于 React 生命周期设置:
componentDidMount() {
setTimeout(() => {
this.addCanvasWebGLContextLossEventListener();
}, 2500);
}
componentWillUnmount() {
this.removeCanvasWebGLContextLossEventListener();
}
需要超时,因为 canvas
元素在安装组件时尚不可用。出于我的目的,短的 2.5 秒计时器为事件处理程序提供了足够的时间来锁定 canvas。
我有一个使用 PixiJS 的数据可视化库的 React 应用程序。
我偶尔会在 Chrome 中遇到令人沮丧的 CONTEXT_LOST_WEBGL
错误,这些错误迫使用户手动重新加载页面,以便(重新)呈现页面。
我不能经常或可靠地重现错误,但我知道它会发生,因为其他人告诉我应用程序偶尔会不显示任何数据。引发此错误的情况似乎非常依赖于上下文,因此很难概括——低功率图形适配器,或同时打开大量选项卡等。
如果最终用户打开了开发者工具控制台 window,则他们只会知道存在 CONTEXT_LOST_WEBGL
错误。否则,网页看起来只是一片空白。
我尝试了以下设置我的 React 应用程序以在 webglcontextlost
事件发生时重新加载 window 而无需用户手动干预:
componentDidMount() {
...
window.addEventListener("webglcontextlost", (e) => { window.location.reload(); });
...
}
我不确定它是否正常工作,即,如果 webglcontextlost
事件正在别处处理。或许我正在尝试订阅错误的事件?
否则,为了更优雅地处理这个问题,有没有办法在原始 Javascript 中或通过第三方库定期测量 WebGL 的可用内存,并使用该测量来代替重新加载页面,当可用内存达到某个可能预测即将发生的 CONTEXT_LOST_WEBGL
错误情况的任意阈值时?
is there a way in raw Javascript to periodically measure available memory for WebGL
没有,就像没有办法测量JavaScript内存
window.addEventListener("webglcontextlost", (e) => { window.location.reload(); });
错了。应该是
someCanvas.addEventListener("webglcontextlost", (e) => { window.location.reload(); });
每个 canvas 都可以单独失去其上下文。大多数浏览器一次只允许 8 到 16 个 WebGL 上下文。一旦达到限制 canvases 就开始失去他们的上下文。
至于优雅地恢复,需要做很多工作。基本上你需要重新创建所有 WebGL 资源,这意味着你需要构建你的代码,这样才有可能。将应用程序的所有状态与与 WebGL 相关的内容(或 pixi.js)分开,当您收到上下文丢失事件时,防止默认并重新创建所有 WebGL 内容
let gl;
someCanvas.addEventListener("webglcontextlost", (e) => {
e.preventDefault(); // allows the context to be restored
});
someCanvas.addEventListener("webglcontextrestored", (e) => {
initWebGL(gl);
});
gl = someCanvas.getContext('webgl');
initWebGL(gl);
请注意,pixi.js 本身可能会或可能不会被设计为处理上下文丢失
当 WebGL 上下文丢失时,以下代码帮助重新启动了我的 Pixijs Web 应用程序:
addCanvasWebGLContextLossEventListener = () => {
const canvases = document.getElementsByTagName("canvas");
if (canvases.length === 1) {
const canvas = canvases[0];
canvas.addEventListener('webglcontextlost', (event) => {
window.location.reload();
});
}
}
removeCanvasWebGLContextLossEventListener = () => {
const canvases = document.getElementsByTagName("canvas");
if (canvases.length === 1) {
const canvas = canvases[0];
canvas.removeEventListener('webglcontextlost');
}
}
对于具有多个 canvas 的其他应用程序,需要进行一些调整以添加其他侦听器。
以下代码帮助我模拟了上下文丢失的情况(并通过 webglcontextlost
事件从中恢复):
simulateWebGLContextLoss = () => {
//
// simulate loss of WebGL context, for the purposes
// of improving user experience when the browser is
// overwhelmed
//
const canvases = document.getElementsByTagName("canvas");
if (canvases.length === 1) {
setTimeout(() => {
const canvas = canvases[0];
const webgl2Context = canvas.getContext("webgl2", {});
if (webgl2Context) {
console.log(`losing webgl2 context...`);
webgl2Context.getExtension('WEBGL_lose_context').loseContext();
}
else {
const webglContext = canvas.getContext("webgl", {});
if (webglContext) {
console.log(`losing webgl context...`);
webglContext.getExtension('WEBGL_lose_context').loseContext();
}
}
}, 5000);
}
}
对于 React 生命周期设置:
componentDidMount() {
setTimeout(() => {
this.addCanvasWebGLContextLossEventListener();
}, 2500);
}
componentWillUnmount() {
this.removeCanvasWebGLContextLossEventListener();
}
需要超时,因为 canvas
元素在安装组件时尚不可用。出于我的目的,短的 2.5 秒计时器为事件处理程序提供了足够的时间来锁定 canvas。