Canvas.toDataURL()在除IE10之外的所有浏览器中工作

Sco*_*dle 13 canvas same-origin-policy cors internet-explorer-10

我正在开发一个项目,它使用画布自动裁剪图像,然后返回其数据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
Run Code Online (Sandbox Code Playgroud)

RRe*_*ser 20

不幸的是,IE10仍然是唯一一个不支持CORS的流行浏览器,即使在正确设置CORS头的情况下也可以将其用于绘制到Canvas的图像.但是,即使没有在服务器端代理图像,也可以通过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();
Run Code Online (Sandbox Code Playgroud)

  • 当url是数据uri时,这不起作用(data:image/svg + xml; base64,...) (9认同)
  • @rreverser我们通过搜索"todataurl"在ie10中找不到这篇文章.虽然这不是问题的原始问题,但似乎如果你在IE10中将base64编码的图像加载到画布中,那么它会污染画布,你不能再在画布上调用toDataUrl. (6认同)
  • 我正在使用fabricJS,并且与IE有同样的问题.我从你的例子中做的唯一改变是revokeObjectURL,直到图像加载了`img.onload = function(e){...}`你可以在这里找到一个完整的例子http://www.html5rocks.com/ EN /教程/文件/ XHR2 /#TOC-reponseTypeBlob (3认同)

Ray*_*lus 6

我不相信IE10对图像有CORS支持. 这篇MDN文章似乎支持了这一点.

正如文章所述:

虽然您可以在画布中使用未经CORS批准的图像,但这样做会污染画布.一旦画布被污染,您就无法再将数据从画布中拉回来.例如,您不能再使用canvas 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);
Run Code Online (Sandbox Code Playgroud)

现在,在服务器端,您将处理此GET请求,source从URI中删除参数的值,从源中获取图像,并在响应中返回它.