Canvas.toDataURL() 适用于除 IE10 以外的所有浏览器
Posted
技术标签:
【中文标题】Canvas.toDataURL() 适用于除 IE10 以外的所有浏览器【英文标题】:Canvas.toDataURL() working in all browsers except IE10 【发布时间】:2013-08-09 08:10:48 【问题描述】:我正在开发一个项目,该项目使用画布自动裁剪图像,然后返回其数据 URL。它使用来自外部服务器的图像,该服务器具有适当的 CORS 标头,以允许图像在被裁剪后转换为数据 URI,即使它们是跨域的。
该代码在除 IE 10 之外的所有浏览器中都能完美运行(并且没有安全错误!),其中在调用 canvas.toDataURL() 时会抛出“SCRIPT5022: SecurityError”。
这是 IE 中的错误还是我需要在我的代码中做一些不同的事情才能使它在 Idiot Exploder 中工作?谢谢。 -斯科特
编辑 这是我用来创建和绘制画布的(大部分)代码;
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
var img = new Image();
img.src = imageServerURL + '?id=' + imageIdToGet; // imageServerURL points to a different domain but the server has headers allowing requests from my domain
/*
code here that defines the cropping area, in variables like ulX, lrY, etc.
*/
ctx.beginPath();
ctx.moveTo(ulX, ulY);
ctx.lineTo(urX, urY);
ctx.lineTo(lrX, lrY);
ctx.lineTo(llX, llY);
ctx.closePath();
ctx.clip();
ctx.drawImage(img, 0, 0);
var url = canvas.toDataURL(); // This succeeds in all other browsers but throws a SecurityError in IE
【问题讨论】:
首先,请向我们展示您的代码和/或说明此画布的创建方式及其包含的内容。 原始问题已编辑。 【参考方案1】:不幸的是,即使正确设置了 CORS 标头,IE10 仍然是唯一不支持绘制到 Canvas 的图像的 CORS 的流行浏览器。但是即使没有在服务器端代理图像,也可以通过 XMLHttpRequest 解决此问题:
var xhr = new XMLHttpRequest();
xhr.onload = function ()
var url = URL.createObjectURL(this.response);
img.src = url;
// here you can use img for drawing to canvas and handling
// don't forget to free memory up when you're done (you can do this as soon as image is drawn to canvas)
URL.revokeObjectURL(url);
;
xhr.open('GET', url, true);
xhr.responseType = 'blob';
xhr.send();
【讨论】:
我正在使用fabricJS,并且在IE中遇到了同样的问题。我必须从您的示例中做的唯一更改是撤销ObjectURL,直到图像加载img.onload = function(e) ...
您可以在此处找到完整示例html5rocks.com/en/tutorials/file/xhr2/#toc-reponseTypeBlob
这在 url 是数据 uri (data:image/svg+xml;base64,...) 时不起作用
@vbarbarosh 当它是数据uri时,它根本与这个问题(关于CORS)无关。
@rreverser 我们通过搜索在 ie10 中不起作用的“todataurl”找到了这篇文章。虽然这不是最初提出的问题,但似乎如果您在 IE10 中将 base64 编码图像加载到画布中,那么它会污染画布,您不能再在画布上调用 toDataUrl。
@agrath 嗯,是的,这不是最初提出的问题,而是有意的安全限制。【参考方案2】:
我认为 IE10 不支持图像的 CORS。 This MDN article 似乎支持这一点。
如文章所述:
尽管您可以在画布中使用未经 CORS 批准的图像,但这样做会污染画布。一旦画布被污染,您就不能再将数据拉出画布。例如,您不能再使用画布的 toBlob()、toDataURL() 或 getImageData() 方法;这样做会引发安全错误。
因此,在尝试执行此操作之前,您似乎必须代理来自与托管相关代码的来源/域相同的图像,至少对于 IE10 和 Opera 而言。
要处理不支持图像 CORS 的浏览器,您需要在服务器端代理图像。您可以通过将图像的源发送到本地服务器上的已知端点,并将图像的源 URL 作为查询参数传递来轻松完成此操作。
例如:
var sourceImageUrl = "https://www.google.com/images/srpr/logo4w.png",
localProxyEndpoint = "/imageproxy",
image = new Image();
image.src = localProxyEndpoint + "?source=" + encodeURIComponent(sourceImageUrl);
现在,在服务器端,您将处理这个 GET 请求,从 URI 中提取 source
参数的值,从源中获取图像,然后在响应中返回它。
【讨论】:
它在 Windows 8 上的 Opera 15 中按预期工作。这个“代理”解决方案需要什么? 可能适用于 Opera 15,因为该版本的 Opera 基于 Chromium。稍后我会编辑我的答案并提供更多详细信息。以上是关于Canvas.toDataURL() 适用于除 IE10 以外的所有浏览器的主要内容,如果未能解决你的问题,请参考以下文章
为啥 canvas.toDataURL() 会抛出安全异常?