FabricJS - "Tainted canvases may not be exported" 当 运行 toDataURL 时出现 JS 错误
FabricJS - "Tainted canvases may not be exported" JS Error when run toDataURL
我有一个名为 ImageContainer 的自定义组件,它主要创建一个矩形并将图像应用为填充图案。
当我在 canvas 上 运行 函数 toDataURL 时,出现 js 错误
Uncaught DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.
我试图达到的结果应该创建一个 png 数据并将其作为 src 应用于图像标签。
知道如何解决吗?
发送
您需要将 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'
后清除缓存。
我有一个名为 ImageContainer 的自定义组件,它主要创建一个矩形并将图像应用为填充图案。
当我在 canvas 上 运行 函数 toDataURL 时,出现 js 错误
Uncaught DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.
我试图达到的结果应该创建一个 png 数据并将其作为 src 应用于图像标签。
知道如何解决吗? 发送
您需要将 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'
后清除缓存。