画布toDataURL()返回空白图像

我正在使用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。

以上是 画布toDataURL()返回空白图像 的全部内容, 来源链接: utcz.com/qa/421346.html

回到顶部