admin管理员组文章数量:1328037
I am using below code to pare two canvas elements
function createImage(html, can) {
var canvas = $( "#" + can );
var ctx = canvas[0].getContext("2d");
var data = "<svg xmlns='' width='1000' height='1000'>" +
"<foreignObject width='100%' height='100%'>" +
"<div xmlns=''>" +
html +
"</div>" +
"</foreignObject>" +
"</svg>";
var DOMURL = self.URL || self.webkitURL || self;
var img = new Image();
img.crossOrigin = '';
var svg = new Blob([data], { type: "image/svg+xml;charset=utf-8" });
var url = DOMURL.createObjectURL(svg);
img.onload = function () {
ctx.drawImage(img, 0, 0);
DOMURL.revokeObjectURL(url);
};
img.src = url;
//return img.src;
return canvas[0];
}
var a1 = createImage("<span style='font-size:34px'><i><b>Hello</b></i></span>","can1");
var a2 = createImage("<span style='font-size:34px'><i><b>Hello</b></i></span>", "can2");
setTimeout(function() {
var ctx1 = a1.getContext('2d');
var imageData = ctx1.getImageData(0, 0, a1.width, a1.height);
var pixels = imageData.data;
var ctx2 = a2.getContext('2d');
var imageData2 = ctx2.getImageData(0, 0, a2.width, a2.height);
var pixels2 = imageData2.data, count;
for(var i = 0, il = pixels.length; i < il; i++) {
if(pixels[i] == pixels2[i]){
count++;
}
}
if(count === pixels.length && count === pixels2.length){
alert("Match");
}
},5000);
But it is returning me error like below
Unable to get image data from canvas because the canvas has been tainted by cross-origin data.
How can I get rid of this error?
I am using below code to pare two canvas elements
function createImage(html, can) {
var canvas = $( "#" + can );
var ctx = canvas[0].getContext("2d");
var data = "<svg xmlns='http://www.w3/2000/svg' width='1000' height='1000'>" +
"<foreignObject width='100%' height='100%'>" +
"<div xmlns='http://www.w3/1999/xhtml'>" +
html +
"</div>" +
"</foreignObject>" +
"</svg>";
var DOMURL = self.URL || self.webkitURL || self;
var img = new Image();
img.crossOrigin = '';
var svg = new Blob([data], { type: "image/svg+xml;charset=utf-8" });
var url = DOMURL.createObjectURL(svg);
img.onload = function () {
ctx.drawImage(img, 0, 0);
DOMURL.revokeObjectURL(url);
};
img.src = url;
//return img.src;
return canvas[0];
}
var a1 = createImage("<span style='font-size:34px'><i><b>Hello</b></i></span>","can1");
var a2 = createImage("<span style='font-size:34px'><i><b>Hello</b></i></span>", "can2");
setTimeout(function() {
var ctx1 = a1.getContext('2d');
var imageData = ctx1.getImageData(0, 0, a1.width, a1.height);
var pixels = imageData.data;
var ctx2 = a2.getContext('2d');
var imageData2 = ctx2.getImageData(0, 0, a2.width, a2.height);
var pixels2 = imageData2.data, count;
for(var i = 0, il = pixels.length; i < il; i++) {
if(pixels[i] == pixels2[i]){
count++;
}
}
if(count === pixels.length && count === pixels2.length){
alert("Match");
}
},5000);
But it is returning me error like below
Unable to get image data from canvas because the canvas has been tainted by cross-origin data.
How can I get rid of this error?
Share Improve this question edited Jun 25, 2015 at 14:30 Diptendu 2,1581 gold badge17 silver badges30 bronze badges asked May 2, 2013 at 12:24 ExceptionException 8,38924 gold badges88 silver badges141 bronze badges 3- Your canvas is being populated (at least in part) by a different domain to where your script is running - thus you can't read it as it would allow data to leack across the domain boundary, vuilating the same origin policy. The only way to avoid this is make sure all the scripts are running on the same domain – Basic Commented May 2, 2013 at 12:28
- @Basic Actually I am paring these two Canvas elements from Content Script of Chrome extension.. Even in localhost I can see the same problem.. – Exception Commented May 2, 2013 at 12:34
- 1 Hmmmm interesting - it wouldn't surprise me if Chrome extensions have some quirks around how the security model is applied but I'm afraid I can't help your further - Hopefully someone else will be able to – Basic Commented May 2, 2013 at 12:38
2 Answers
Reset to default 5The reason you get a cross-origin error is because of the use of <svg>
with namespace declarations located at http://www.w3/
, which is of a different origin:
var data = "<svg xmlns='http://www.w3/2000/svg' width='1000' height='1000'>" +
"<foreignObject width='100%' height='100%'>" +
"<div xmlns='http://www.w3/1999/xhtml'>" +
html +
"</div>" +
"</foreignObject>" +
"</svg>";
I can tell this method is the one from Drawing DOM objects into a canvas on MDN.
When you re-access the data this way,
var ctx1 = a1.getContext('2d');
var imageData = ctx1.getImageData(0, 0, a1.width, a1.height);
you will hit the error:
Unable to get image data from canvas because the canvas has been tainted by cross-origin data.
You can test this on Chrome:
- Your original version with the error
- Another version with namespace declarations removed, which does not throw an error and is at the same time blank due to the absence of namespace declarations
You can only return the data from the function to avoid getting this error. But because of the asynchronous nature of img.onload
,
img.onload = function () {
ctx.drawImage(img, 0, 0);
DOMURL.revokeObjectURL(url);
};
you have to defer the retrieval of data, forcing you to re-access the data out of the function and causing the error.
Thus, you should use an alternate method of building the canvas with DOM objects that does not rely on <svg>
, like html2canvas.
function createImage(html) {
var dfd = new $.Deferred();
var el = document.createElement("div");
el.innerHTML = html;
el.style.display = 'inline-block';
document.body.appendChild(el);
html2canvas(el, {
onrendered: function(canvas) {
document.body.appendChild(canvas);
document.body.removeChild(el);
dfd.resolve(canvas.toDataURL());
}
});
return dfd;
}
$.when(
createImage("<span style='font-size:34px'><i><b>Hello</b></i></span>"),
createImage("<span style='font-size:34px'><i><b>Hello</b></i></span>")
).done(function(a1, a2){
if (a1 === a2) {
alert("Match");
}
});
See DEMO.
About the "cross origin policy" problems
Unable to get image data from canvas because the canvas has been tainted by cross-origin data. SECURITY_ERR: DOM Exception 18
It's a security issue caused by the navigator "cross origin policy".
This error will appear if you have "dirtied" your canvas. This is done by drawing images to the canvas that are from a different origin. For instance, if your canvas is hosted at www.example., and you use images from www.wikipedia, then your canvas origin-clean
flag is set to false
internally.
Once the origin-clean flag is set to false
, you are no longer allowed to call toDataURL
or getImageData
Technically, images are of the same origin if domains, protocols, and ports match.
If you are working locally (file://) then any image drawn will set off the flag. This makes debugging annoying, but with Chrome you can start it with the flag --allow-file-access-from-files
to allow this.
To learn more read the article: "Understanding the HTML5 Canvas image security rules".
Credits to Simon Sarris
My files are in the same domain or the chrome flag is activated and I still get this error, what's happening?
The problem is that Chrome (currently) always taints a canvas when an SVG document is drawn to it.
For a more detailed explanation see the question below:
Rasterizing an in-document SVG to Canvas
Ok, the use of svg seems to be the problem, so how to fix it?
At the time of my writing Antony answered it!
See his answer.
本文标签: javascriptTrying to compare two Canvas elementsStack Overflow
版权声明:本文标题:javascript - Trying to compare two Canvas elements - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742242621a2438929.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论