尝试比较两个Canvas元素 [英] Trying to compare two Canvas elements

查看:98
本文介绍了尝试比较两个Canvas元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用下面的代码来比较两个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上测试:





只能从函数返回数据以避免得到这个错误。但是由于 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:

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆