I have a custom component called ImageContainer, which basically creates a rectangle and applies an image as a fill pattern.
When I run function toDataURL on the canvas, I get a js error
Uncaught DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.
The result I trying to achieve should create a png data and apply it on image tag as a src.
Any idea how could it be fixed? Tnx
You need to add crossOrigin: 'anonymous'
to the image element. Have added in fabric.Image.fromURL
, or you need to use images from same server, or where crossOrigin is defined.
DEMO
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" />