如何在 PixiJS 中更优雅地处理 WebGL CONTEXT_LOST_WEBGL 错误? [英] How to handle WebGL CONTEXT_LOST_WEBGL errors more gracefully in PixiJS?

查看:238
本文介绍了如何在 PixiJS 中更优雅地处理 WebGL CONTEXT_LOST_WEBGL 错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 React 应用程序,它使用了一个使用 PixiJS 的数据可视化库.

I have a React application that uses a data visualization library that uses PixiJS.

我偶尔会在 Chrome 中遇到令人沮丧的 CONTEXT_LOST_WEBGL 错误,这些错误迫使用户手动重新加载页面,以便(重新)呈现页面.

I occasionally get frustrating CONTEXT_LOST_WEBGL errors in Chrome that force the user to manually reload the page, in order for the page to be (re)rendered.

我无法经常或可靠地重现该错误,但我知道它会发生,因为其他人告诉我该应用程序偶尔不显示任何数据.引发此错误的情况似乎非常依赖于上下文,因此难以概括 - 低功耗图形适配器或同时打开大量标签等.

I cannot often or reliably reproduce the error, but I know that it happens as other people tell me the application occasionally shows no data. The situations that raise this error seem very context-dependent and therefore difficult to recapitulate — low-powered graphics adapters, or lots of tabs open at once, etc.

最终用户只有在打开开发者工具控制台窗口时才会知道存在 CONTEXT_LOST_WEBGL 错误.否则,网页看起来只是空白.

The end user would only know that there are CONTEXT_LOST_WEBGL errors if that user has the Developer Tools console window open. Otherwise, the web page just looks blank.

当发生 webglcontextlost 事件时,我尝试了以下方法来设置我的 React 应用程序以重新加载窗口,而无需用户手动干预:

I have tried the following to set up my React application to reload the window without manual user intervention, when a webglcontextlost event occurs:

componentDidMount() {
  ...
  window.addEventListener("webglcontextlost", (e) => { window.location.reload(); });
  ...
}

我不确定它是否正常工作,,如果 webglcontextlost 事件正在其他地方处理.或者,也许我试图订阅错误的事件?

I'm not sure it is working correctly, i.e., if the webglcontextlost event is being handled elsewhere. Or perhaps I am trying to subscribe to the wrong event?

否则,要尝试更优雅地处理这个问题,是否有一种方法可以在原始 Javascript 中或通过第三方库来定期测量 WebGL 的可用内存,并使用该测量值来代替重新加载页面,当可用内存达到某个任意阈值,可能会预测即将发生的 CONTEXT_LOST_WEBGL 错误情况?

Otherwise, to try to handle this more gracefully, is there a way in raw Javascript, or via a third-party library, to periodically measure available memory for WebGL, and to use that measurement to instead reload the page, when the available memory reaches some arbitrary threshold that might predict an imminent CONTEXT_LOST_WEBGL error condition?

推荐答案

当 WebGL 上下文丢失时,以下代码帮助重新启动了我的 Pixijs Web 应用程序:

The following code helped restart my Pixijs web application, when the WebGL context is lost:

  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');
    }
  }

对于具有多个画布的其他应用程序,需要进行一些调整以添加其他侦听器.

For other applications with more than one canvas, some adjustments would be needed to add other listeners.

以下代码帮助我模拟丢失的上下文条件(并通过 webglcontextlost 事件从中恢复):

The following code helped me simulate a lost context condition (and to restore from it, via the webglcontextlost event):

  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 生命周期设置:

For React lifecycle setup:

  componentDidMount() {
    setTimeout(() => { 
      this.addCanvasWebGLContextLossEventListener();
    }, 2500);
  }

  componentWillUnmount() {
    this.removeCanvasWebGLContextLossEventListener();
  }

需要超时,因为在组件挂载时 canvas 元素尚不可用.就我而言,2.5 秒的短计时器为事件处理程序提供了足够的时间来锁定画布.

A timeout is required, as the canvas element is not yet available when the component mounts. For my purposes, the short 2.5s timer provides enough time for the event handler to latch onto the canvas.

这篇关于如何在 PixiJS 中更优雅地处理 WebGL CONTEXT_LOST_WEBGL 错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆