我们开发复杂的WebGL应用程序,并为用户提供保存当前场景的屏幕截图的功能。虽然此功能在Chrome和Firefox中正常运行,但我们在safari中遇到了几个问题。
请查看以下代码。如您所见,我们使用CanvasElement的toDataURL()方法来制作屏幕截图。虽然此代码在其他浏览器中按预期工作,但它会在safari中生成错误的图像(至少对于WebGL画布)。
您可以通过在Safari和其他浏览器中打开this file或运行附加的代码段轻松地重现此问题。
我们做错了吗?这个问题有解决方法吗?
谢谢。
UPD:特别是对于那些说它与preserveDrawingBuffer有关的人我更改为附加的代码片段来显示即使将preserveDrawingBuffer设置为true,它仍然在safari中表现不正确。
<script type="text/javascript" src="http://www.html5rocks.com/en/tutorials/webgl/webgl_fundamentals/webgl/resources/webgl-utils.js"></script>
<script id="2d-vertex-shader" type="x-shader/x-vertex">
attribute vec2 a_position;
void main() {
gl_Position = vec4(a_position, 0, 1);
}
</script>
<script id="2d-fragment-shader" type="x-shader/x-fragment">
void main() {
gl_FragColor = vec4(0,1,0,1); // green
}
</script>
<div>
<canvas id="canvas1" width="300" height="300"></canvas>
<img id="img1"/>
</div>
<div>
<canvas id="canvas2" width="300" height="300"></canvas>
<img id="img2"/>
</div>
<div>
<canvas id="canvas3" width="300" height="300"></canvas>
<img id="img3"/>
</div>
<div>
<canvas id="canvas4" width="300" height="300"></canvas>
<img id="img4"/>
</div>
<div>
<canvas id="canvas5" width="300" height="300"></canvas>
<img id="img5"/>
</div>
<div>
<canvas id="canvas6" width="300" height="300"></canvas>
<img id="img6"/>
</div>
<script type="text/javascript">
function test(canvas, img, premultipliedAlpha, alpha, preserveDrawingBuffer) {
var gl = canvas.getContext("experimental-webgl", {
premultipliedAlpha: premultipliedAlpha,
alpha: alpha,
preserveDrawingBuffer: preserveDrawingBuffer
});
var vertexShader = createShaderFromScriptElement(gl, "2d-vertex-shader");
var fragmentShader = createShaderFromScriptElement(gl, "2d-fragment-shader");
var program = createProgram(gl, [vertexShader, fragmentShader]);
gl.useProgram(program);
var positionLocation = gl.getAttribLocation(program, "a_position");
var buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(
gl.ARRAY_BUFFER,
new Float32Array([
-1.0, -1.0,
1.0, -1.0,
-1.0, 1.0,
1.0, -1.0,
1.0, 1.0]),
gl.STATIC_DRAW);
gl.enableVertexAttribArray(positionLocation);
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
gl.drawArrays(gl.TRIANGLES, 0, 5);
img.src = canvas.toDataURL();
}
window.onload = function() {
test(document.getElementById("canvas1"), document.getElementById("img1"), true, true, false);
test(document.getElementById("canvas2"), document.getElementById("img2"), false, true, false);
test(document.getElementById("canvas3"), document.getElementById("img3"), false, false, false);
test(document.getElementById("canvas4"), document.getElementById("img4"), true, true, true);
test(document.getElementById("canvas5"), document.getElementById("img5"), false, true, true);
test(document.getElementById("canvas6"), document.getElementById("img6"), false, false, true);
};
</script>
&#13;
答案 0 :(得分:1)
在 Mac 和 iPhone 上的 Safari 中,当 premultipliedAlpha: false
创建 webgl
上下文时,toDataURL
返回垂直翻转的图像。
这个错误在 2021 年仍然存在于 Safari 中。作为一种解决方法,我们可以复制到具有 2d
上下文的画布,将画布数据复制到该画布并调用 toDataURL
。
function getDataUrl(origCanvas, mimeType){
var canvas = document.createElement( 'canvas' );
canvas.width = origCanvas.width;
canvas.height = origCanvas.height;
var destCtx = canvas.getContext('2d');
if(!destCtx) {
console.error("Cannot create context")
return ""
}
destCtx?.drawImage(origCanvas, 0, 0);
return destCtx.canvas.toDataURL(mimeType);
}
答案 1 :(得分:0)
我自己偶然发现了这个问题。我认为这只是safari中的一个错误:当你在获取gl上下文时设置premultipliedAlpha:false时,canvas.toDataURL()将返回一个颠倒的图像。向Apple发送了一个错误报告。