可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
My code is working very well on my localhost but it is not working on the site.
I got this error from the console, for this line .getImageData(x,y,1,1).data
:
Uncaught SecurityError: Failed to execute \'getImageData\' on \'CanvasRenderingContext2D\': The canvas has been tainted by cross-origin data.
part of my code:
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;
}
Note: my image url (src) is from a subdomain url
回答1:
As others have said you are \"tainting\" the canvas by loading from a cross origins domain.
https://developer.mozilla.org/en-US/docs/HTML/CORS_Enabled_Image
However, you may be able to prevent this by simply setting:
img.crossOrigin = \"Anonymous\";
This only works if the remote server sets the following header appropriately:
Access-Control-Allow-Origin \"*\"
The Dropbox file chooser when using the \"direct link\" option is a great example of this. I use it on oddprints.com to hoover up images from the remote dropbox image url, into my canvas, and then submit the image data back into my server. All in javascript :)
回答2:
I found that I had to use .setAttribute(\'crossOrigin\', \'\')
and had to append a timestamp to the URL\'s query string to avoid a 304 response lacking the Access-Control-Allow-Origin
header.
This gives me
var url = \'http://lorempixel.com/g/400/200/\';
var imgObj = new Image();
imgObj.src = url + \'?\' + new Date().getTime();
imgObj.setAttribute(\'crossOrigin\', \'\');
回答3:
You won\'t be able to draw images directly from another server into a canvas and then use getImageData
. It\'s a security issue and the canvas will be considered \"tainted\".
Would it work for you to save a copy of the image to your server using PHP and then just load the new image? For example, you could send the URL to the PHP script and save it to your server, then return the new filename to your javascript like this:
<?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;
?>
You\'d use the PHP script with some ajax javascript like this:
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;
}
}
If you use getImageData
on the canvas after that, it will work fine.
Alternatively, if you don\'t want to save the whole image, you could pass x & y coordinates to your PHP script and calculate the pixel\'s rgba value on that side. I think there are good libraries for doing that kind of image processing in PHP.
If you want to use this approach, let me know if you need help implementing it.
回答4:
Your problem is that you load an external image, meaning from another domain. This causes a security error when you try to access any data of your canvas context.
回答5:
You are \"tainting\" the canvas by loading from a cross origins domain. Check out this MDN article:
https://developer.mozilla.org/en-US/docs/HTML/CORS_Enabled_Image
回答6:
As matt burns says in his answer, you may need to enable CORS on the server where the problem images are hosted.
If the server is Apache, this can be done by adding the following snippet (from here) to either your VirtualHost config or an .htaccess
file:
<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>
...if adding it to a VirtualHost, you\'ll probably need to reload Apache\'s config too (eg. sudo service apache2 reload
if Apache\'s running on a Linux server)
回答7:
I was having the same issue, and for me it worked by simply concatenating https:${image.getAttribute(\'src\')}
回答8:
When working on local add a server
I had a similar issue when working on local. You url is going to be the path to the local file e.g. file:///Users/PeterP/Desktop/folder/index.html.
Please note that I am on a MAC.
I got round this by installing http-server globally. https://www.npmjs.com/package/http-server
Steps:
- Global install:
npm install http-server -g
- Run server:
http-server ~/Desktop/folder/
PS: I assume you have node installed, otherwise you wont get very far running npm commands.
回答9:
I meet the same problem today, and solve it by the code follows.
html code:
<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 code:
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)
}
code like above, and there is no cross-domain problem.