FabricJS - 运行到数据URL时"Tainted canvases may not be exported" JS错误



我有一个名为ImageContainer的自定义组件,它基本上创建了一个矩形并将图像作为填充图案应用。

当我在画布上运行函数到数据URL时,我收到js错误

Uncaught DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.

我试图实现的结果应该创建一个 png 数据并将其作为 src 应用于图像标签。

知道如何修复它吗? 嘟嘟

https://jsfiddle.net/redlive/a444p13x/

您需要向图像元素添加crossOrigin: 'anonymous'。已添加fabric.Image.fromURL,或者您需要使用来自同一服务器的图像,或者定义了 crossOrigin 的图像。

演示

fabric.ImageContainer = fabric.util.createClass(fabric.Rect, {
type: 'image-container',
initialize: function(options) {
	  options || (options = { });
options.content || (options.content = { });
options.content.angle = options.content.angle || 0;

this.callSuper('initialize', options);
this.set({
objectCaching: false,
ddpPreviousCenter: this.getCenterPoint()
});

this.on('scaling', function(el){
this.set({
	      width: this.width * this.scaleX,
height: this.height * this.scaleY,
scaleX: 1,
scaleY: 1
});
this.setCoords();
this._drawImage();
}.bind(this));

this.on('modified', function(el){
				this._updateContentCoords();
}.bind(this));

this._drawImage();        
},
_updateContentCoords: function(){
		const ddpPreviousCenter = {...this.ddpPreviousCenter};
const content = {...this.content};
const shiftX = this.getCenterPoint().x - ddpPreviousCenter.x;
const shiftY = this.getCenterPoint().y - ddpPreviousCenter.y;
content.left += shiftX;
content.top += shiftY;

this.set({
ddpPreviousCenter: this.getCenterPoint(),
content
});
},
_drawImage: function() {
const scaleFactor = 1;
const imgSrc = [
'https://picsum.photos/',
this.content.width * scaleFactor,
'/',
this.content.height * scaleFactor
].join('');
fabric.Image.fromURL(imgSrc, function(img) {
img.set({
left: this.content.left - this.left + this.content.width / 2,
top:  this.content.top - this.top + this.content.height / 2,
scaleX: 1,
scalY: 1,
angle: this.content.angle,
originX: 'center',
originY: 'center',
});
//            img.scaleToWidth(this.content.width);
const patternSourceCanvas = new fabric.StaticCanvas();
patternSourceCanvas.setDimensions({
width: this.width,
height: this.height
});
	patternSourceCanvas.setBackgroundColor(this.backgroundColor);
patternSourceCanvas.add(img);
patternSourceCanvas.renderAll();
const pattern = new fabric.Pattern({
	source: function() {
return patternSourceCanvas.getElement();
},
repeat: 'no-repeat'
});

this.set({
fill: pattern
});
this.canvas.renderAll();
this.canvas.fire('image:pattern:loaded');

}.bind(this),{
crossOrigin: 'anonymous'
});
},
toObject: function(options) {
return fabric.util.object.extend(this.callSuper('toObject'), {
ddpPreviousCenter: this.get('ddpPreviousCenter'),
content: this.get('content'),
});
// return fabric.util.object.extend(this.callSuper('toObject'), {});
},
fromObject: function(object, callback) {
	return fabric.Object._fromObject('ImageContainer', object, callback);
	},
_render: function(ctx) {
this.callSuper('_render', ctx);
}
});
fabric.ImageContainer.__fromObject = function(object, callback, forceAsync) {
if (!forceAsync) {
fabric.util.enlivenPatterns([object.fill, object.stroke], function(patterns) {
console.log(patterns);
object.fill = patterns[0];
object.stroke = patterns[1];
var rect = new fabric.ImageContainer(object);
callback && callback(rect);
});
}
else {
var rect = new fabric.ImageContainer(object);
callback && callback(rect);
return rect;
}
};
// =========================================================================
let store;
const canvas = new fabric.Canvas('paper');
const container = new fabric.ImageContainer({
left: 10,
top: 10,
width: 150,
height: 150,
backgroundColor: 'green',
content: {
left: 20,
top: 20,
width: 130,
height: 130
}
});
canvas.on('image:pattern:loaded', function(){
$('#img').attr('src', this.toDataURL());
});
canvas.add(container);
canvas.renderAll();
#paper {
border: solid 1px red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.2.3/fabric.js"></script>
<img id="image" />
<canvas id="paper" width="400" height="200" style="border:1px solid #ccc"></canvas>
<img id="img" />

添加crossOrigin: 'anonymous'后我不得不清除缓存。

这是我解决这个问题的方法。这是因为画布中不能有外部图像 URL。您必须获取映像并创建其本地副本。在我的示例中,我将画布的背景设置为图像,但您可以执行相同的操作将图像添加到画布。

fetch("https://i.imgur.com/fHyEMsl.jpg")
.then(result => result.blob())
.then(blob => {
const url = URL.createObjectURL(blob);
fabric.Image.fromURL(url, function (Image) {
canvas.setBackgroundImage(Image);
canvas.renderAll();
})
});
fabric.Image.fromURL(imgSrc, (img) => {
img._element.crossOrigin = 'anonymous'
canvas.add(img).requestRenderAll()
})

相关内容

最新更新