如何解决getImageData()错误canvas已被交叉源数据污染?
我的代码在我的本地主机上工作得很好,但是它不能在网站上工作。
我得到这个错误从控制台,这一行.getImageData(x,y,1,1).data
:
Uncaught SecurityError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data.
我的部分代码:
jQuery.Event.prototype.rgb=function(){ var x = this.offsetX || (this.pageX - $(this.target).offset().left),y = this.offsetY || (this.pageY - $(this.target).offset().top); if (this.target.nodeName!=="CANVAS")return null; return this.target.getContext('2d').getImageData(x,y,1,1).data; }
注意:我的图片url(src)来自子网站的url
正如其他人所说,你是从一个跨域来加载“canvas”。
https://developer.mozilla.org/en-US/docs/HTML/CORS_Enabled_Image
但是,您可以通过简单设置来防止这种情况:
img.crossOrigin = "Anonymous";
这只适用于远程服务器正确设置以下标题:
Access-Control-Allow-Origin "*"
使用“直接链接”选项时, Dropbox文件select器就是一个很好的例子。 我在oddprints.com上使用它将来自远程Dropbox图像URL的图像拖入我的canvas,然后将图像数据提交回我的服务器。 全部在JavaScript 🙂
我发现我必须使用.setAttribute('crossOrigin', '')
并且必须在URL的查询string后附加一个时间戳,以避免缺lessAccess-Control-Allow-Origin
头的304响应。
这给了我
var url = 'http://lorempixel.com/g/400/200/'; var imgObj = new Image(); imgObj.src = url + '?' + new Date().getTime(); imgObj.setAttribute('crossOrigin', '');
您将无法直接从另一台服务器中将图像绘制到canvas上,然后使用getImageData
。 这是一个安全问题,canvas将被视为“污点”。
它会工作为您保存图像的副本到您的服务器使用PHP,然后加载新的图像? 例如,您可以将URL发送到PHP脚本并将其保存到您的服务器,然后将新的文件名返回到您的JavaScript,如下所示:
<?php //The name of this file in this example is imgdata.php $url=$_GET['url']; $img = file_get_contents($url); $fn = substr(strrchr($url, "/"), 1); file_put_contents($fn,$img); echo $fn; ?>
你会使用PHP脚本与一些Ajax的JavaScript像这样:
xi=new XMLHttpRequest(); xi.open("GET","imgdata.php?url="+yourImageURL,true); xi.send(); xi.onreadystatechange=function() { if(xi.readyState==4 && xi.status==200) { img=new Image; img.onload=function(){ ctx.drawImage(img, 0, 0, canvas.width, canvas.height); } img.src=xi.responseText; } }
如果之后在canvas上使用getImageData
,它将正常工作。
或者,如果您不想保存整个图像,则可以将x和y坐标传递给PHP脚本,并计算该像素的rgba值。 我认为在PHP中进行这种image processing有很好的库。
如果你想使用这种方法,让我知道如果你需要帮助实施它。
你的问题是你加载一个外部的图像,意思是从另一个域。 当您尝试访问您的canvas上下文的任何数据时,这会导致安全性错误。
您从“跨源”域加载“画”canvas。 看看这个MDN文章:
https://developer.mozilla.org/en-US/docs/HTML/CORS_Enabled_Image
我今天遇到同样的问题,并按照代码解决。
html代码:
<div style='display: none'> <img id='img' src='img/iak.png' width='600' height='400' /> </div> <canvas id='iak'>broswer don't support canvas</canvas>
js代码:
var canvas = document.getElementById('iak') var iakImg = document.getElementById('img') var ctx = canvas.getContext('2d') var image = new Image() image.src=iakImg.src image.onload = function () { ctx.drawImage(image,0,0) var data = ctx.getImageData(0,0,600,400) }
代码如上,并没有跨域问题。
由于亚光烧伤在他的回答中提到,您可能需要在托pipe问题图像的服务器上启用CORS。
如果服务器是Apache,可以通过将以下代码片段(从这里 )添加到您的VirtualHostconfiguration文件或.htaccess
文件来完成:
<IfModule mod_setenvif.c> <IfModule mod_headers.c> <FilesMatch "\.(cur|gif|ico|jpe?g|png|svgz?|webp)$"> SetEnvIf Origin ":" IS_CORS Header set Access-Control-Allow-Origin "*" env=IS_CORS </FilesMatch> </IfModule> </IfModule>
…如果将其添加到VirtualHost,您可能还需要重新加载Apache的configuration(例如,如果Apache在Linux服务器上运行, sudo service apache2 reload
)