Fabric.Js Images cropped when loading from json

sushilronghe
2 min readSep 10, 2020

--

Recently i was presented with a problem of cropped images. There is a angularJS application which uses FabricJS canvas to render images & text. For those who don’t know FabricJs, its a canvas which allows to render images, text, shapes etc.. on canvas. It also allows to serialize and de-serialize canvas content into json. The app was originally using fabricjs 1.7.x version and recently they migrated to 2.2.4. Since the migration the image were getting cropped when json data is loaded into the canvas.

Initial finding suggested that Fabricjs has made breaking changed into v2 and provided drop-in replacement for migration. However the replacement did not worked. The FromObject function was getting called by fabric but still images were showing cropped on the canvas.

Solution :

Instead of depending on the FromObject function, I decided to pre-process the json and modify the image object width and height. Once i passed this pre-process json to loadFromJson function everything worked as expected. A complete solution is provided here.

preProcess(json).then((json1) => {
canvas.loadFromJSON(json1, canvas.renderAll.bind(canvas), (o, object) => {
})
})
//All done render canvas now.
canvas.renderAll();
var preProcess = async function(images) {
return new Promise((resolve, reject) => {
const promiseArray = []
images.forEach((group) => {
group.objects.forEach((obj) => {
if (obj.type == "image") {
//Images from assets works fine so not modifying them..You can do some more processing with url here if required.
if (url.indexOf("./assets") != 0) {
promiseArray.push(myLoadImage3(obj));
}
}
})
})
Promise.all(promiseArray).then((res) => {
resolve({
objects: images
});
})
})
}
var myLoadImage3 = function(object, j, i) {
return new Promise((resolve, reject) => {
fabric.util.loadImage(object.src, function(img, error) {
var elWidth = img.naturalWidth || img.width;
var elHeight = img.naturalHeight || img.height;
var scaleX = (object.scaleX || 1) * object.width / elWidth;
var scaleY = (object.scaleY || 1) * object.height / elHeight;
object.width = elWidth;
object.height = elHeight;
object.scaleX = scaleX;
object.scaleY = scaleY;
resolve(object.src);
}, null, object.crossOrigin);
})
};

Hope it will help someone. Also if i migrate the Fabricjs from v2 to v3 and then v4 i will post any valuable findings.

--

--

sushilronghe
sushilronghe

Written by sushilronghe

Full Stack Developer | technologies | Cloud Specialist

No responses yet