boy*_*oyd 17 javascript firefox canvas webgl 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);
}
Run Code Online (Sandbox Code Playgroud)
我的图像的路径也在同一个域上;
问题(在Firefox中)是我点击保存按钮.Chrome会返回预期的结果,但Firefox会返回此信息:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA7YAAAIWCAYAAABjkRHCAAAHxklEQVR4nO3BMQEAAADCoPVPbQZ/oAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
... [ lots of A s ] ...
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAzwD6aAABkwvPRgAAAABJRU5ErkJggg==
Run Code Online (Sandbox Code Playgroud)
什么可能导致这个结果,我该如何解决?
gma*_*man 22
很可能在您绘制画布的时间和调用的时间之间存在一些异步事件toDataURL.默认情况下,画布在每个复合后清除.无论是防止画布由与创建WebGL的情况下被清除preserveDrawingBuffer: true,如
var gl = canvas.getContext("webgl", {preserveDrawingBuffer: true});
Run Code Online (Sandbox Code Playgroud)
或者确保在退出用于渲染的任何事件之前调用toDataURL.例如,如果你这样做
function render() {
drawScene();
requestAnimationFrame(render);
}
render();
Run Code Online (Sandbox Code Playgroud)
而其他地方也这样做
someElement.addEventListener('click', function() {
var data = someCanvas.toDataURL();
}, false);
Run Code Online (Sandbox Code Playgroud)
这两个事件,animation frame和,click不同步,画布可以在调用它们之间清除.注意:画布不会被清除,因为它是双缓冲的,但缓冲区toDataURL和其他影响该缓冲区的命令被清除.
解决方案是使用preserveDrawingBuffer或toDataURL在与渲染相同的事件内进行调用.例如
var captureFrame = false;
function render() {
drawScene();
if (captureFrame) {
captureFrame = false;
var data = someCanvas.toDataURL();
...
}
requestAnimationFrame(render);
}
render();
someElement.addEventListener('click', function() {
captureFrame = true;
}, false);
Run Code Online (Sandbox Code Playgroud)
什么preserveDrawingBuffer: false是默认值?它可以明显更快,特别是在移动设备上,不必保留绘图缓冲区.另一种看待它的方法是浏览器需要2个画布副本.你正在绘制的那个和它正在显示的那个.它有两种方法来处理这两个缓冲区.(A)双缓冲.让你绘制一个,显示另一个,当你完成渲染时交换缓冲区,这是从退出任何发出绘制命令的事件推断出来的.(B)复制你正在绘制的缓冲区的内容来做正在显示的缓冲区.交换比复制快得多.因此,交换是默认值.这取决于浏览器实际发生的事情.唯一的要求是,如果preserveDrawingBuffer是false将绘制缓冲区得到复合后清除(这又是一个异步事件,因此无法预测的),如果preserveDrawingBuffer是true,那么它必须复制,以便drawingbuffer的内容被保留.
请注意,一旦画布具有上下文,它将始终具有相同的上下文.换句话说,假设您更改了初始化WebGL上下文但仍需要设置的代码preserveDrawingBuffer: true
至少有两种方式.
因为代码稍后将以相同的上下文结束.
<script>
document.querySelector('#somecanvasid').getContext(
'webgl', {preserveDrawingBuffer: true});
</script>
<script src="script/that/will/use/somecanvasid.js"></script>
Run Code Online (Sandbox Code Playgroud)
因为您已经为该画布创建了一个上下文,无论后面的脚本获得相同的上下文.
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>
Run Code Online (Sandbox Code Playgroud)
在这种情况下,在扩充getContextwill 之后创建的任何webgl上下文都preserveDrawingBuffer设置为true.
| 归档时间: |
|
| 查看次数: |
8783 次 |
| 最近记录: |