在Chrome中,当我尝试从远程网址测试画布绘制图像时,我在jsfiddle上收到以下错误。
错误:无法执行' toDataURL' on' HTMLCanvasElement':可能无法导出受污染的画布。
在S3存储桶上,我有以下CORS策略,允许跨资源共享:
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
</CORSRule>
</CORSConfiguration>
如果我使用jsfiddle作为原点卷曲图像:
curl -H 'Origin: https://fiddle.jshell.net' -I 'https://i.ezr.io/products3/472_ARDSCR.jpg?h=45&w=165&fit=scale'
HTTP/1.1 200 OK
Cache-Control: public,max-age=31536000
Last-Modified: Wed, 07 Feb 2018 23:42:47 GMT
Server: imgix-fe
Content-Length: 6371
Accept-Ranges: bytes
Date: Fri, 16 Mar 2018 17:10:20 GMT
Age: 3173253
Connection: keep-alive
Content-Type: image/jpeg
Access-Control-Allow-Origin: *
X-Content-Type-Options: nosniff
X-Served-By: cache-lax8630-LAX, cache-sea1027-SEA
X-Cache: HIT, HIT
var Rack = {
init: function(params) {
Rack.conf = params;
Rack.bindEvents();
},
bindEvents: function() {
Rack.conf.scaleDown.addEventListener("click", function() {
Rack.clearCanvas();
Rack.conf.scaleW = Rack.round(Rack.conf.scaleW - .1, 1);
Rack.conf.scaleY = Rack.round(Rack.conf.scaleY - .1, 1);
if (Rack.conf.scaleW > 0 && Rack.conf.scaleY > 0) {
Rack.build();
}
});
Rack.conf.resetScale.addEventListener("click", function() {
Rack.clearCanvas();
Rack.conf.scaleW = 1;
Rack.conf.scaleY = 1;
Rack.build(true);
});
Rack.getRackJSON();
Rack.setNumImages();
Rack.build();
},
getRackJSON: function() { // will send ajax call based on item being added to the rack, will return json rack
Rack.conf.rack = {
"awards": [{
"src": "https://i.ezr.io/products3/472_ARDSCR.jpg?h=45&w=165&fit=scale",
"name": "Army Distinguished Service Cross",
"sku": "472_ARDSCR",
"x": 0,
"y": 0,
"width": 165,
"height": 45,
"attachments": [{
"src": "https://i.ezr.io/products3/913NP.png?h=20",
"name": "Bronze Oak Leaf",
"sku": "913NP",
"x": 73,
"y": 13,
"width": 20,
"height": 20
}]
},
{
"src": "https://i.ezr.io/products3/470_ARDDR.jpg?h=45&w=165&fit=scale",
"name": "Department of Defense Distinguished Service",
"sku": "470_ARDDR",
"x": 165,
"y": 0,
"width": 165,
"height": 45
}
]
};
},
setNumImages() {
for (var i = 0; i < Rack.conf.rack.awards.length; i++) {
var award = Rack.conf.rack.awards[i];
++Rack.conf.numImages;
if (award.hasOwnProperty('attachments')) {
Rack.conf.numImages += award.attachments.length;
}
}
},
loadImages: function(callback) {
var numImagesLoaded = 0;
for (var i = 0; i < Rack.conf.rack.awards.length; i++) {
var award = Rack.conf.rack.awards[i];
Rack.conf.images[award.sku] = new Image();
Rack.conf.images[award.sku].onload = function() {
if (++numImagesLoaded >= Rack.conf.numImages) {
callback();
}
}
Rack.conf.images[award.sku].src = award.src;
if (award.hasOwnProperty('attachments')) {
for (var j = 0; j < award.attachments.length; j++) {
var attachment = award.attachments[j];
Rack.conf.images[attachment.sku] = new Image();
Rack.conf.images[attachment.sku].crossOrigin = 'anonymous';
Rack.conf.images[attachment.sku].onload = function() {
if (++numImagesLoaded >= Rack.conf.numImages) {
callback();
}
}
Rack.conf.images[attachment.sku].src = attachment.src;
}
}
}
},
build: function(reset) {
if (Rack.conf.outputType === 'jpg') {
Rack.conf.ctx.fillStyle = "#ffffff";
Rack.conf.ctx.fillRect(0, 0, Rack.conf.c.width, Rack.conf.c.height);
}
reset === true ? Rack.conf.ctx.setTransform(1, 0, 0, 1, 0, 0) : Rack.conf.ctx.scale(Rack.conf.scaleW, Rack.conf.scaleY);
Rack.loadImages(function() {
for (var i = 0; i < Rack.conf.rack.awards.length; i++) {
var award = Rack.conf.rack.awards[i];
Rack.conf.ctx.drawImage(Rack.conf.images[award.sku], award.x, award.y, award.width, award.height);
if (award.hasOwnProperty('attachments')) {
for (var j = 0; j < award.attachments.length; j++) {
var attachment = award.attachments[j];
Rack.conf.ctx.drawImage(Rack.conf.images[attachment.sku], attachment.x, attachment.y, attachment.width, attachment.height);
}
}
}
});
Rack.conf.imageData = Rack.conf.c.toDataURL((Rack.conf.outputType === 'jpg' ? 'image/jpeg' : null), (Rack.conf.outputType === 'jpg' ? 1.0 : null));
},
clearCanvas: function() {
Rack.conf.ctx.clearRect(0, 0, Rack.conf.c.width, Rack.conf.c.height);
},
round: function(number, precision) {
var factor = Math.pow(10, precision);
var tempNumber = number * factor;
var roundedTempNumber = Math.round(tempNumber);
return roundedTempNumber / factor;
}
};
Rack.init({
c: document.getElementById("myCanvas"),
ctx: document.getElementById("myCanvas").getContext("2d"),
outputType: 'png',
scaleDown: document.getElementById('scale-down'),
resetScale: document.getElementById('reset-scale'),
images: {},
numImages: 0,
awards: null,
imageData: null,
scaleW: 1,
scaleY: 1,
rack: null
});
&#13;
<canvas id="myCanvas" width="330" height="45">Your browser does not support the HTML5 canvas tag.</canvas>
<div>
<button id="scale-down" style="cursor:pointer;">
Scale Down
</button>
<button id="reset-scale" style="cursor:pointer;">
Reset
</button>
</div>
&#13;
答案 0 :(得分:3)
您现在已经知道了问题的答案,即添加Rack.conf.images[award.sku].crossOrigin = 'anonymous';
以下是解释需要的类似问题的主题
https://github.com/locomotivecms/engine/issues/1152
toDataURL throw Uncaught Security exception
https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image
什么是&#34;污染&#34;帆布吗
虽然您可以在画布中使用未经CORS批准的图像,但这样做会污染画布。一旦画布被污染,您就无法再将数据从画布中拉回来。例如,您不能再使用canvas toBlob(),toDataURL()或getImageData()方法;这样做会引发安全错误。
这可以防止用户在未经许可的情况下使用图像从远程网站提取信息来暴露私有数据。
答案 1 :(得分:2)
问题解决了:缺少Rack.conf.images [award.sku] .crossOrigin =&#39; anonymous&#39;;