我使用下面的代码来比较两个画布元素
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);
但它正在回复我的错误如下
无法从画布获取图像数据,因为画布已被跨源数据污染。
如何摆脱这个错误?
答案 0 :(得分:5)
您遇到跨源错误的原因是因为<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, 0, a1.width, a1.height);
你会遇到错误:
无法从画布获取图像数据,因为画布已被跨源数据污染。
您可以在Chrome上进行测试:
您只能从函数返回数据以避免出现此错误。但由于img.onload
的异步性,
img.onload = function () {
ctx.drawImage(img, 0, 0);
DOMURL.revokeObjectURL(url);
};
您必须推迟检索数据,强制您从函数中重新访问数据并导致错误。
因此,您应该使用另一种方法来构建画布,其中DOM对象不依赖于<svg>
,如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。
答案 1 :(得分:1)
无法从画布获取图像数据,因为画布已被跨源数据污染。 SECURITY_ERR:DOM例外18
这是导航器“交叉原始政策”导致的安全问题。
如果您的画布“弄脏了”,则会出现此错误。这是通过将图像绘制到来自不同来源的画布来完成的。例如,如果您的画布托管在www.example.com,并且您使用的是www.wikipedia.org中的图像,那么您的画布origin-clean
标志将在内部设置为false
。
将origin-clean标志设置为false
后,您将不再被允许致电toDataURL
或getImageData
从技术上讲,如果域,协议和端口匹配,图像的来源相同。
如果您在本地工作(file://),那么绘制的任何图像都会将标志设置为off。这会使调试变得烦人,但使用Chrome时,您可以使用标记--allow-file-access-from-files
启动它以允许此操作。
要了解详情,请阅读文章:“Understanding the HTML5 Canvas image security rules”。
的信用问题是Chrome(当前)在绘制SVG文档时总是玷污画布。
有关更详细的说明,请参阅以下问题:
<强> Rasterizing an in-document SVG to Canvas 强>
在我写作的时候,安东尼回答了它!