FabricJS:使用图像子类时无法执行 'drawImage'
FabricJS: Failed to execute 'drawImage' when using an Image subclass
对于一个项目,我需要将各种类型的图像添加到 canvas,保存到 JSON 并再次加载。不同的类型没有任何特定的属性,我只需要类型不同。
我在 fabric.Image 的基础上创建了一个新的 class,如下所示:
fabric.Icon = fabric.util.createClass(fabric.Image, {
type: "icon",
initialize: function (element, options) {
this.callSuper("initialize", element, options);
},
_render: function (ctx) {
this.callSuper("_render", ctx);
},
});
fabric.Icon.fromObject = function (object, callback) {
return fabric.Object._fromObject("Icon", object, callback);
};
在此之后,我使用 SVG 图像添加了这种新类型的新对象:
let newImage = new Image(); //HTML Image type, not FabricJS
newImage.onload = () => {
let icon = new fabric.Icon(newImage); //my subclass of fabric.Image class
this.canvas.add(icon);
};
newImage.src = "image.svg";
当我使用
将canvas导出到JSON时
let savedJSON = canvas.toJSON()
并用
加载回来
canvas.loadFromJSON(savedJSON, function () {
canvas.requestRenderAll();
}
我收到以下错误
Uncaught TypeError: Failed to execute 'drawImage' on 'CanvasRenderingContext2D': The provided value is not of type '(CSSImageValue or HTMLImageElement or SVGImageElement or HTMLVideoElement or HTMLCanvasElement or ImageBitmap or OffscreenCanvas)'
当我使用标准 fabric.Image class 时,一切正常。我应该在我的 subclass 中重写其他方法吗?或者我应该以其他方式区分各种图像类型?
好吧,这不是解决这个问题的真正方法,但我找到了区分在保存和加载过程中持续存在的对象的正确方法 - 通过覆盖其在 Object.prototype 上设置自定义 属性 toObject 方法如下:
Fabric js extending toObject with custom properties, loses default ones
问题已解决!
fabric 图像 class 具有稍微复杂的恢复机制,因为它需要构造函数中的图像元素,该元素不可序列化。
这是它在 fabricJS 中的实现方式:
/**
* Creates an instance of fabric.Image from its object representation
* @static
* @param {Object} object Object to create an instance from
* @param {Function} callback Callback to invoke when an image instance is created
*/
fabric.Image.fromObject = function(_object, callback) {
var object = fabric.util.object.clone(_object);
fabric.util.loadImage(object.src, function(img, isError) {
if (isError) {
callback && callback(null, true);
return;
}
fabric.Image.prototype._initFilters.call(object, object.filters, function(filters) {
object.filters = filters || [];
fabric.Image.prototype._initFilters.call(object, [object.resizeFilter], function(resizeFilters) {
object.resizeFilter = resizeFilters[0];
fabric.util.enlivenObjects([object.clipPath], function(enlivedProps) {
object.clipPath = enlivedProps[0];
var image = new fabric.Image(img, object);
callback(image, false);
});
});
});
}, null, object.crossOrigin);
};
恐怕你必须复制它并将 fabric.Image 替换为 fabric.Icon
对于一个项目,我需要将各种类型的图像添加到 canvas,保存到 JSON 并再次加载。不同的类型没有任何特定的属性,我只需要类型不同。
我在 fabric.Image 的基础上创建了一个新的 class,如下所示:
fabric.Icon = fabric.util.createClass(fabric.Image, {
type: "icon",
initialize: function (element, options) {
this.callSuper("initialize", element, options);
},
_render: function (ctx) {
this.callSuper("_render", ctx);
},
});
fabric.Icon.fromObject = function (object, callback) {
return fabric.Object._fromObject("Icon", object, callback);
};
在此之后,我使用 SVG 图像添加了这种新类型的新对象:
let newImage = new Image(); //HTML Image type, not FabricJS
newImage.onload = () => {
let icon = new fabric.Icon(newImage); //my subclass of fabric.Image class
this.canvas.add(icon);
};
newImage.src = "image.svg";
当我使用
将canvas导出到JSON时let savedJSON = canvas.toJSON()
并用
加载回来canvas.loadFromJSON(savedJSON, function () {
canvas.requestRenderAll();
}
我收到以下错误
Uncaught TypeError: Failed to execute 'drawImage' on 'CanvasRenderingContext2D': The provided value is not of type '(CSSImageValue or HTMLImageElement or SVGImageElement or HTMLVideoElement or HTMLCanvasElement or ImageBitmap or OffscreenCanvas)'
当我使用标准 fabric.Image class 时,一切正常。我应该在我的 subclass 中重写其他方法吗?或者我应该以其他方式区分各种图像类型?
好吧,这不是解决这个问题的真正方法,但我找到了区分在保存和加载过程中持续存在的对象的正确方法 - 通过覆盖其在 Object.prototype 上设置自定义 属性 toObject 方法如下: Fabric js extending toObject with custom properties, loses default ones 问题已解决!
fabric 图像 class 具有稍微复杂的恢复机制,因为它需要构造函数中的图像元素,该元素不可序列化。
这是它在 fabricJS 中的实现方式:
/**
* Creates an instance of fabric.Image from its object representation
* @static
* @param {Object} object Object to create an instance from
* @param {Function} callback Callback to invoke when an image instance is created
*/
fabric.Image.fromObject = function(_object, callback) {
var object = fabric.util.object.clone(_object);
fabric.util.loadImage(object.src, function(img, isError) {
if (isError) {
callback && callback(null, true);
return;
}
fabric.Image.prototype._initFilters.call(object, object.filters, function(filters) {
object.filters = filters || [];
fabric.Image.prototype._initFilters.call(object, [object.resizeFilter], function(resizeFilters) {
object.resizeFilter = resizeFilters[0];
fabric.util.enlivenObjects([object.clipPath], function(enlivedProps) {
object.clipPath = enlivedProps[0];
var image = new fabric.Image(img, object);
callback(image, false);
});
});
});
}, null, object.crossOrigin);
};
恐怕你必须复制它并将 fabric.Image 替换为 fabric.Icon