javascript – 为什么转换为图片后我的画布变成了空白?

我正在尝试使用以下代码段将this page上的canvas元素转换为png(例如,在JavaScript控制台中输入):

(function convertCanvasToImage(canvas) {
  var image = new Image();
  image.src = canvas.toDataURL("image/png");
  return image;
})($$('canvas')[0]);

不幸的是,我得到的png是完全空白的.另请注意,调整页面大小后原始画布将变为空白.

为什么画布变成空白?如何将此画布转换为png?

Kevin Reid的preserveDrawingBuffer建议是正确的,但有(通常)更好的选择. tl; dr是最后的代码.

将渲染网页的最终像素组合在一起并将其与渲染WebGL内容进行协调可能会非常昂贵.通常的流程是:

> JavaScript向WebGL上下文发出绘制命令
> JavaScript返回,将控制权返回给主浏览器事件循环
> WebGL上下文将绘图缓冲区(或其内容)转换为合成器,以便集成到当前正在屏幕上呈现的网页中
>具有WebGL内容的页面显示在屏幕上

请注意,这与大多数OpenGL应用程序不同.在那些中,渲染的内容通常直接显示,而不是与页面上的一堆其他东西合成,其中一些实际上可能在WebGL内容之上并与之混合.

在步骤3之后,WebGL规范被更改为将绘图缓冲区视为基本上为空.您在devtools中运行的代码将在步骤4之后出现,这就是为什么您得到一个空缓冲区.对规范的这一更改允许在平台上实现大幅性能改进,其中步骤3之后的消隐基本上是硬件中实际发生的情况(如在许多移动GPU中).如果你想在第3步之后解决这个问题,有时会复制WebGL内容,浏览器必须在第3步之前总是复制绘图缓冲区,这会使你的帧率在某些平台上急剧下降.

您可以通过将preserveDrawingBuffer设置为true来强制执行此操作并强制浏览器进行复制并保持图像内容的可访问性.从规格:

This default behavior can be changed by setting the preserveDrawingBuffer attribute of the WebGLContextAttributes object. If this flag is true, the contents of the drawing buffer shall be preserved until the author either clears or overwrites them. If this flag is false, attempting to perform operations using this context as a source image after the rendering function has returned can lead to undefined behavior. This includes readPixels or toDataURL calls, or using this context as the source image of another context’s texImage2D or drawImage call.

在您提供的示例中,代码只是更改上下文创建行:

gl = canvas.getContext("experimental-webgl", {preserveDrawingBuffer: true});

请记住,它会强制某些浏览器中的慢速路径和性能受到影响,具体取决于渲染的内容和方式.你应该在大多数桌面浏览器中都没问题,这些浏览器实际上并不需要制作副本,而且这些浏览器组成了绝大多数支持WebGL的浏览器……但仅限于现在.

但是,还有另一种选择(在规范的下一段中有点令人困惑地提到).

基本上,您在第2步之前自己制作副本:在完成所有绘制调用之后但在您从代码中将控制权返回给浏览器之前.这是当WebGL绘图缓冲区仍然可以访问时,您应该可以轻松访问像素.你使用相同的toDataUrl或readPixels调用,否则它只是重要的时间.

在这里,您将获得两全其美.你得到了一个绘图缓冲区的副本,但是你不需要在每一帧中付费,即使那些你不需要副本(可能是其中大部分)的那些,就像你将preserveDrawingBuffer设置为true一样.

在您提供的示例中,只需将代码添加到drawScene的底部,您就会看到右下方的画布副本:

function drawScene() {
  ...

  var webglImage = (function convertCanvasToImage(canvas) {
    var image = new Image();
    image.src = canvas.toDataURL('image/png');
    return image;
  })(document.querySelectorAll('canvas')[0]);

  window.document.body.appendChild(webglImage);
}
翻译自:https://stackoverflow.com/questions/12538193/why-does-my-canvas-go-blank-after-converting-to-image

转载注明原文:javascript – 为什么转换为图片后我的画布变成了空白?