I’m working on image cropping using the latest Fabric.js. Initially, when a user adds an image to the canvas, I call the getImgPolarId() function and store the image data in the currentImg global variable. When the user double-clicks on the canvas, I call the applyCropToImage() function. In this function, I create a backgroundImg with the same state as currentImg, setting the original image as that backgroundImg. I then apply a clipPath to the original image. After clicking on the canvas, I generate a new image that includes only the clipped portion. When applying the crop again, I want to remove the base URL image from the canvas and use the original image again, but I’m encountering an error like…
ERROR TypeError: Cannot read properties of undefined (reading 'getRetinaScaling')
at klass.drawControls (fabric.js:18058:39)
at klass._renderControls (fabric.js:15860:28)
at klass.drawControls (fabric.js:12876:22)
at klass.renderCanvas (fabric.js:9799:14)
at klass.renderAll (fabric.js:12062:12)
at klass.renderAndReset (fabric.js:9735:12)
at timer (zone.js:2367:41)
at _ZoneDelegate.invokeTask (zone.js:402:31)
at core.mjs:10757:55
at AsyncStackTaggingZoneSpec.onInvokeTask (core.mjs:10757:36)
// Initially add Image Element in canvas
getImgPolaroid(image_details, uploadfrom = '', st: any = {}, stickerFrom: string = '') {
var id, that = this;
fabric.util.loadImage(image_details, (imgObj) => {
var image = new fabric.Image(imgObj);
image.crossOrigin = "anonymous";
image.set({
left: that.utils.getCenterCoord(imgObj.width * scale, that.zoomWidthRef),
top: that.utils.getCenterCoord(imgObj.height * scale, that.zoomHeightRef),
angle: 0,
padding: 0,
hasRotatingPoint: true,
peloas: 12,
isLocked: false,
id: this.generateUniqueId(),
cornerSize: 15,
cornerColor: '#00C3F9',
cornerStyle: 'circle',
lockScalingFlip: true,
clipTo: null,
excludeFromExport: false,
transparentCorners: false,
});
setTimeout(() => {
that.canvas.add(image);
that.canvas.centerObject(image);
this.canvas.setActiveObject(image);
this.currentImg = image;
that.canvas.renderAll();
}, 500);
}, null, { crossOrigin: 'anonymous' });
return id;
}
// apply cropping functionality to image on double-clicks
applyCropToImage(image, activeobject) {
// set background image same as a original
var backgroundImg = new fabric.Image(image.getElement(), {
left: this.getClippathleft - this.whatLeftDiff,
top: this.getClippathtop - this.whatTopDiff,
scaleX: image.scaleX,
scaleY: image.scaleY,
opacity: 0.3,
selectable: true,
});
backgroundImg.setCoords();
this.canvas.add(backgroundImg);
var index = this.canvas.getObjects().indexOf(image);
backgroundImg.moveTo(index);
image.set({});
const rect = new fabric.Rect({
left: this.getClippathleft,
top: this.getClippathtop,
width: this.getClippathwidth,
height: this.getClippathheight,
cornerSize: 15,
cornerColor: '#00C3F9',
cornerStyle: 'circle',
selectable: false,
evented: true,
absolutePositioned: true,
type: 'crop',
transparentCorners: false,
centeredScaling: false,
centeredRotation: true,
lockScalingFlip: true,
lockMovementX: true,
lockMovementY: true,
_controlsVisibility: {
tl: true,
tr: true,
br: true,
bl: true,
ml: false,
mt: false,
mr: false,
mb: false,
mtr: false
},
});
image.setCoords();
rect.setCoords();
image.clipPath = rect;
this.canvas.setActiveObject(image.clipPath);
this.canvas.on({
'mouse:down': (e) => {
this.whatLeftDiff = rect.left - image.left;
this.whatTopDiff = rect.top - image.top;
const newRect = image.clipPath;
// Create a new image instance from cropped area
var croppedImg = new Image();
croppedImg.src = this.canvas.toDataURL({
left: newRect.left,
top: newRect.top,
width: newRect.width,
height: newRect.height,
});
croppedImg.onload = () => {
this.canvas.remove(image);
const newImage = new fabric.Image(croppedImg);
newImage.left = newRect.left;
newImage.top = newRect.top;
newImage.isCroped = true;
newImage.element_type = "stockphotos";
newImage.cornerSize = 15;
newImage.cornerColor = '#00C3F9';
newImage.cornerStyle = 'circle';
newImage.transparentCorners = false;
newImage.setCoords();
this.canvas.add(newImage);
// Remove clip path and background image (optional)
image.clipPath = null;
this.canvas.remove(backgroundImg);
this.canvas.renderAll();
}
this.canvas.renderAll();
},
this.canvas.requestRenderAll();
})
}