Tainted canvases may not be exported
For security reasons, your local drive is declared to be "other-domain" and will taint the canvas.
(That's because your most sensitive info is likely on your local drive!).
While testing try these workarounds:
Put all page related files (.html, .jpg, .js, .css, etc) on your desktop (not in sub-folders).
Post your images to a site that supports cross-domain sharing (like dropbox.com or GitHub). Be sure you put your images in dropbox's public folder and also set the cross origin flag when downloading the image (
var img=new Image(); img.crossOrigin="anonymous"
...)Install a webserver on your development computer (IIS and PHP web servers both have free editions that work nicely on a local computer).
Canvas.toDataURL() Tainted canvases may not be exported
There are a couple ways to get around this, but all of them will require at least temporarily hosting the image on your server. The simplest option would be to write a simple cgi script that takes an url as a parameter, fetches the image at that url, and sends it on to the browser as though it was on your server. You could also use a file upload form if you want the user to be able to select a local image.
Note that if you do this, you would want to be aware of the security implications of grabbing user-selected files and serving them as if they were on your own server. You would, at a minimum, want to make sure the files were valid images, and not, say, javascript files (which might lead to code injection attacks).
The reason exporting of tainted canvas data is disallowed is that it's a user security issue. Remote sites can send different images to different users, and if your site can gain access to that just by drawing it on a canvas, that method could be used to steal a user's private data. For example, Amazon used to let website owners embed an image in their site that would end up being a customized ad including a greeting and the end-user's name. If you could paint that on a canvas and export the data, you could send that data back to your webserver and OCR it to learn the name of the end-user.
toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported
Problem solved: Was missing Rack.conf.images[award.sku].crossOrigin = 'anonymous';
FabricJS - Tainted canvases may not be exported JS Error when run toDataURL
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" />
Related Topics
Pad a Number With Leading Zeros in JavaScript
Why Do You Need to Invoke an Anonymous Function on the Same Line
JavaScript Inheritance and the Constructor Property
JavaScript - Track Mouse Position
JavaScript and Operator Within Assignment
Get Computed Font-Family in JavaScript
Toggle Visibility Property of Div
Google Maps Not Rendering Completely on Page
Example of How to Load Static CSS Files from Node_Modules Using Webpack
Is "Monkey Patching" Really That Bad
How to Post Urlencoded Form Data With $Http Without Jquery
Angularjs: How to Pass Variables Between Controllers
Merge Two Array of Objects Based on a Key
Tainted Canvases May Not Be Exported
Meaning of "This" in Node.Js Modules and Functions
Read CSS Property of an Element Using JavaScript
Change CSS of Class in JavaScript
How to Transition the Flex-Grow of a Flex Box to Produce an Animation