尝试比较两个Canvas元素 [英] Trying to compare two Canvas elements
问题描述
我使用下面的代码来比较两个canvas元素。
函数createImage(html,can){
var canvas = $(#+ can);
var ctx = canvas [0] .getContext(2d);
var data =< svg xmlns ='http://www.w3.org/2000/svg'width ='1000'height ='1000'> +
< foreignObject width ='100%'height ='100%'> +
< div xmlns ='http://www.w3.org/1999/xhtml'> +
html +
< / div> +
< / foreignObject> +
< / svg>;
var DOMURL = self.URL || self.webkitURL ||自;
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><跨度>中, 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 if(pixels [i] = = pixels2 [i]){
count ++;
}
}
if(count === pixels.length&& count === pixels2.length){
alert(Match);
}
},5000);
但它会返回错误,如下所示
< blockquote>
无法从画布获取图片数据,因为画布已被交叉源数据污染。
我怎样才能摆脱这个错误?
你得到一个交叉错误的原因是因为使用< svg>
命名空间声明位于 http://www.w3.org/
,这是一个不同的来源:
var data =< svg xmlns ='http://www.w3.org/2000/svg 'width ='1000'height ='1000'> +
< foreignObject width ='100%'height ='100%'> +
< div xmlns ='http://www.w3.org/1999/xhtml'> +
html +
< / div> +
< / foreignObject> +
< / svg>;
我可以告诉这个方法是在MDN中将DOM对象绘制到画布上。
当您重新访问数据时
var ctx1 = a1.getContext('2d');
var imageData = ctx1.getImageData(0,0,a1.width,a1.height);
您将遇到以下错误:
无法从画布获取图片数据,因为画布已被交叉源数据污染。
您可以在Chrome上测试:
- 您的原始版本 a>带有错误
- 删除了名称空间声明的另一个版本,它不会抛出由于缺少名称空间声明,所以出现错误并且同时为空
只能从函数返回数据以避免得到这个错误。但是由于 img.onload
,
img的异步性质, onload = function(){
ctx.drawImage(img,0,0);
DOMURL.revokeObjectURL(url);
};
您必须推迟数据的检索,迫使您重新访问数据并导致错误。因此,您应该使用不依赖于< svg>的DOM对象构建画布的替代方法。
,例如 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);
}
});
请参阅 DEMO 。
I am using below code to compare two canvas elements
function createImage(html, can) {
var canvas = $( "#" + can );
var ctx = canvas[0].getContext("2d");
var data = "<svg xmlns='http://www.w3.org/2000/svg' width='1000' height='1000'>" +
"<foreignObject width='100%' height='100%'>" +
"<div xmlns='http://www.w3.org/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?
The reason you get a cross-origin error is because of the use of <svg>
with namespace declarations located at http://www.w3.org/
, which is of a different origin:
var data = "<svg xmlns='http://www.w3.org/2000/svg' width='1000' height='1000'>" +
"<foreignObject width='100%' height='100%'>" +
"<div xmlns='http://www.w3.org/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.
这篇关于尝试比较两个Canvas元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!