当前位置: 首页 > 面试题库 >

画布toDataURL()返回空白图像

云鸿达
2023-03-14
问题内容

我正在使用glfx.js编辑我的图像,但是当我尝试使用toDataURL()函数获取该图像的数据时,我得到了一个空白图像(宽度与原始图像相同)。

奇怪的是,在Chrome中,脚本可以完美运行。

我要提及的是,canvas使用onload事件加载了图像:

           img.onload = function(){

                try {
                    canvas = fx.canvas();
                } catch (e) {
                    alert(e);
                    return;
                }

                // convert the image to a texture
                texture = canvas.texture(img);

                // draw and update canvas
                canvas.draw(texture).update();

                // replace the image with the canvas
                img.parentNode.insertBefore(canvas, img);
                img.parentNode.removeChild(img);

            }

另外,我的图片路径在同一域中;

问题(在Firefox中)是当我按下“保存”按钮时。Chrome返回预期结果,但Firefox返回以下结果:

data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA7YAAAIWCAYAAABjkRHCAAAHxklEQVR4nO3BMQEAAADCoPVPbQZ/oAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
... [ lots of A s ] ... 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAzwD6aAABkwvPRgAAAABJRU5ErkJggg==

是什么导致此结果,如何解决?


问题答案:

最有可能在您绘制画布到调用之间有一些异步事件toDataURL。默认情况下,每个合成后都会清除画布。通过使用来创建WebGL上下文,preserveDrawingBuffer:true以防止清除画布。

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

或确保在退出用于渲染的任何事件之前调用toDataURL。例如,如果您这样做

function render() {
  drawScene(); 
  requestAnimationFrame(render);
}
render();

而在其他地方

someElement.addEventListener('click', function() {
  var data = someCanvas.toDataURL();
}, false);

animationframe,和这两个事件click不同步,在调用它们之间可以清除画布。注意:画布不会被清除,因为它是双重缓冲的,但是toDataURL的缓冲和影响该缓冲正在查看的其他命令已清除。

解决方案是使用preserveDrawingBuffertoDataURL在与渲染相同的事件中调用您的方法。例如

var captureFrame = false;

function render() {
  drawScene();

  if (captureFrame) {
    captureFrame = false;
    var data = someCanvas.toDataURL();
    ...
  }

  requestAnimationFrame(render);
}
render();

someElement.addEventListener('click', function() {
  captureFrame = true;
}, false);

什么preserveDrawingBuffer: false是默认值?它可以显着提高速度,尤其是在移动设备上,不必保留绘图缓冲区。另一种查看方式是浏览器需要2个画布副本。您要绘制的图形和正在显示的图形。它有2种方法来处理这2个缓冲区。(一)双缓冲。让您绘制一个,显示另一个,完成渲染后交换缓冲区,这是从退出发出绘制命令的任何事件推断出来的(B)复制您要绘制的缓冲区的内容以执行正在显示的缓冲区。交换比复制快得多。因此,交换是默认设置。实际发生的情况取决于浏览器。唯一的要求是,如果preserveDrawingBufferfalse如果复合,则绘图缓冲区将被清除(这是另一个异步事件,因此是不可预测的),如果preserveDrawingBuffer是,true则必须复制它,以便保留绘图缓冲区的内容。

注意,一旦画布具有上下文,它将始终具有相同的上下文。因此,换句话说,假设您更改了初始化WebGL上下文的代码,但仍要设置preserveDrawingBuffer:true

至少有两种方法。

首先找到画布,在其上获取上下文

因为后面的代码最终将具有相同的上下文。

<script>
document.querySelector('#somecanvasid').getContext(
    'webgl', {preserveDrawingBuffer: true});
</script>
<script src="script/that/will/use/somecanvasid.js"></script>

因为您已经为该画布创建了上下文,所以之后的任何脚本都将获得相同的上下文。

增加 getContext

<script>
HTMLCanvasElement.prototype.getContext = function(origFn) {
  return function(type, attributes) {
    if (type === 'webgl') {
      attributes = Object.assign({}, attributes, {
        preserveDrawingBuffer: true,
      });
    }
    return origFn.call(this, type, attributes);
  };
}(HTMLCanvasElement.prototype.getContext);
</script>
<script src="script/that/will/use/webgl.js"></script>

在这种情况下,在扩充之后创建的任何webgl上下文getContext都将preserveDrawingBuffer设置为true。



 类似资料:
  • 问题内容: 我想上传图像文件,将它们绘制到画布中,进行更改并将其保存在数据库中。我尝试测试画布图像()返回的base64值,该值为空白。但是,当我将canvas()附加到文档时,会看到结果。我在这里做错了什么? 问题答案: 我的直觉说,所有内容都应纳入功能中。 这意味着,在相关部分,代码变为: 原因是行 加载图像后正确执行。但不幸的是,执行此行时,您不必等待加载: 和所有后续行。 需要加载图像才能

  • 我正在构建我的第一个Spring Boot应用程序。但是我不能正确地得到我的requestMapping控制器的回答。 这是我的主要课程: 这是我的RestController: 如果我看一下日志,我可以看到“/hi”映射: 但是当我访问:http:localhost:8080/hi时,我看到了一个空白页面,我期望看到“Hello World”文本。 为什么我得到一个空白页面? ---编辑----

  • 问题内容: 我有一个看起来像这样的JSON Blob 我有一些代码将其转换回go结构 但是我在运行时看到的只是一个零位结构 我尝试先分配该结构,但那也没有用,我不确定为什么它不产生值,并且不返回错误 问题答案: 您的结构字段不会导出。这是因为它们以小写字母开头。 当我说“未导出”时,是指它们在您的包装之外不可见。您的软件包可以愉快地访问它们,因为它们在本地作用域内。 至于包装-它看不到它们。您需要

  • 我正在尝试使用FFMPEG设置画布动画到视频的转换。瓦斯姆。其思想是使用然后将它们发送到节点服务器以生成视频。我正在从公共目录中提取预上传的图像进行测试,但是当我尝试发送一组(或一个)使用我收到以下错误: 我试图替换画布。toDataURL()与,但是这也没有帮助。下面是我正在使用的剪切代码: 正面: 后端: 上面的代码经过简化,可以制作一个单个图像循环30秒的视频。同样,使用预上传的图像非常有效

  • 我对REST编程很陌生。 下面是我的类,它打算返回XML/JSON,但我很难让它返回正确的值。我尝试返回我的POJO类的Response、JsonArray和Object,但没有成功。我看了好几条线索,但都搞不清到底是什么问题。 资源类: POJO类: 这是我返回响应或朋友对象时得到的: 当返回< code>JsonArray时,我得到的是: 我面临的另一个问题是:如果我创建一个构造函数,我得到以

  • 我能够从URL发送JSON响应,然后当我在RecyclerView上显示相同的响应时,得到的输出是空白的,但选项卡和导航抽屉仍然存在。运行该应用程序时也没有错误。我也在使用截击库。 问题:我在列出服务的RecylerView上没有得到任何输出。我会在这里贴出与RecyclerView相关的代码。另外,我已经在底部发布了堆栈跟踪。 serviceViewAdapter.java(适配器) fragm