【问题标题】:CanvasContext2D drawImage() issue [onload and CORS]CanvasContext2D drawImage() 问题 [onload 和 CORS]
【发布时间】:2015-12-29 02:21:17
【问题描述】:

我正在尝试在得到 dataURL() 之前在画布上绘制图像,但返回的数据就像是空的。

当我在控制台中查看时,我看到字符串中有很多 A : ("data:image/png;base64,iVBO..some random chars... bQhfoAAAAAAAAAA... a lot of A ...AAAASUVORK5CYII=")

当我尝试将画布附加到文档时,也没有绘制任何内容,并且我没有在控制台中引发任何错误。

这里有什么问题?

这是我的代码:

var img = new Image();
img.src = "http://somerandomWebsite/picture.png";
var canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
var context = canvas.getContext('2d');
context.drawImage(img, 0,0); // this doesn't seem to work
var dataURL = canvas.toDataURL(); // this will give me a lot of "A"    
doSomething(dataURL);

此外,在进行快速刷新时,图像会正确绘制到画布上,但我在控制台中收到一条错误消息,dataURL 为空。

Firefox 中的消息是:“SecurityError: The operation is insecure.”,
在 Chrome 中是 “未捕获的 SecurityError:无法在 'HTMLCanvasElement' 上执行 'toDataURL':可能无法导出受污染的画布。”,
而在 IE 上我只得到 "SecurityError"

什么意思?

【问题讨论】:

  • 这篇文章旨在成为我们了解这个特定问题的 20 周左右的规范文章。请告诉我是否可以改进。
  • 不只是在对图像做任何事情之前加载图像更相关吗?如果您认为参考 toDataURL 有用,您应该提及(可能的)CORS 问题。无论如何 +1 为维基的想法/努力。
  • @GameAlchemist 你是对的,我试图将这两个问题结合起来,因为它们非常相似并且经常成对出现。我在答案中谈到了CORS问题。不知道搜索引擎会如何处理这个问题,也许我应该在问题中添加“画布被污染”消息错误。无论如何,我要求将问题也转换为wiki,这样您就可以编辑它。

标签: javascript canvas html5-canvas


【解决方案1】:

您必须等待图像加载,然后才能在画布上进行绘制。

为此,只需使用 <img> 元素的 load 事件处理程序即可:

// create a new image
var img = new Image();
// declare a function to call once the image has loaded
img.onload = function(){
  var canvas = document.createElement('canvas');
  canvas.width = img.width;
  canvas.height = img.height;
  var context = canvas.getContext('2d');
  context.drawImage(img, 0,0);
  var dataURL = canvas.toDataURL();
  // now you can do something with the dataURL
  doSomething(dataURL);
}
// now set the image's src
img.src = "http://somerandomWebsite/picture.png";

另外,为了使画布的context.toDataURL()context.getImageData 正常工作,您必须在cross-origin compliant way 中获取图像资源,否则画布会被“污染”,这意味着任何获取像素数据的方法都会被阻止。

  • 如果您的图片来自同一个服务器,没问题。
  • 如果您的图像是从外部服务器提供的,请确保它允许您的跨域标头出现,并将img.crossOrigin 设置为"use-credentials"
  • 如果服务器确实允许匿名请求,您可以将img.crossOrigin设置为"anonymous"

Nota Bene : CORS header is sent by the servercross-origin 属性只会让它知道你想使用 CORS 来获取图像数据,如果服务器设置不正确,您绝对无法绕过它。
还有一些 UserAgents (IE & Safari) 还没有实现这个属性。

Edge Case :如果您的一些图像来自您的服务器,而另一些来自符合 CORS 的图像,那么您可能需要使用 onerror 事件处理程序,如果您设置cross-origin 属性为非 CORS 服务器上的 "anonymous"

function corsError(){
  this.crossOrigin='';
  this.src='';
  this.removeEventListener('error', corsError, false);
} 
img.addEventListener('error', corsError, false);

【讨论】:

    猜你喜欢
    • 2014-07-24
    相关资源
    最近更新 更多