我正在使用下面的代码来比较两个画布元素
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); 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,a1.width,a1.height); var pixels = imageData.data; var ctx2 = a2.getContext('2d'); var imageData2 = ctx2.getImageData(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);
但它正在回报我错误如下
Unable to get image data from canvas because the canvas has been tainted by cross-origin data.
如何摆脱这个错误?
解决方法
你得到交叉起始错误的原因是因为使用了< 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>";
我可以说这个方法是从Drawing DOM objects into a canvas on MDN开始的.
当您以这种方式重新访问数据时,
var ctx1 = a1.getContext('2d'); var imageData = ctx1.getImageData(0,a1.height);
你会打错误:
Unable to get image data from canvas because the canvas has been tainted by cross-origin data.
您可以在Chrome上测试:
> Your original version带有错误
> Another version with namespace declarations removed,由于缺少命名空间声明,它不会引发错误,同时也是空白的
您只能从函数返回数据,以避免得到此错误.但是由于img.onload的异步性质,
img.onload = function () { ctx.drawImage(img,0); DOMURL.revokeObjectURL(url); };
您必须延迟检索数据,强制您重新访问该函数中的数据并导致错误.
因此,您应该使用不依赖于< svg>(如html2canvas)的DOM对象来构建画布的备用方法.
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.