I'm currently working with Vue js and Fabric.js and have created a custom shape to support different radius values on each corner, as the built-in rectangle object in Fabric.js does not support this feature. Here's the code for the custom shape:
fabric.RoundedRect = fabric.util.createClass(fabric.Rect, {type: 'roundedRect',initialize: function (options) {options = options || {};this.callSuper('initialize', options);this.set('topLeft', options.topLeft || \[20, 20\]);this.set('topRight', options.topRight || \[20, 20\]);this.set('bottomLeft', options.bottomLeft || \[20, 20\]);this.set('bottomRight', options.bottomRight || \[20, 20\]);},\_render: function (ctx) {var w = this.width,h = this.height,x = -this.width / 2,y = -this.height / 2,/\* "magic number" for bezier approximations of arcs (http://itc.ktu.lt/itc354/Riskus354.pdf) \*/k = 1 - 0.5522847498;ctx.beginPath(); // top left ctx.moveTo(x + this.topLeft[0], y); // line to top right ctx.lineTo(x + w - this.topRight[0], y); ctx.bezierCurveTo( x + w - k * this.topRight[0], y, x + w, y + k * this.topRight[1], x + w, y + this.topRight[1] ); // line to bottom right ctx.lineTo(x + w, y + h - this.bottomRight[1]); ctx.bezierCurveTo( x + w, y + h - k * this.bottomRight[1], x + w - k * this.bottomRight[0], y + h, x + w - this.bottomRight[0], y + h ); // line to bottom left ctx.lineTo(x + this.bottomLeft[0], y + h); ctx.bezierCurveTo( x + k * this.bottomLeft[0], y + h, x, y + h - k * this.bottomLeft[1], x, y + h - this.bottomLeft[1] ); // line to top left ctx.lineTo(x, y + this.topLeft[1]); ctx.bezierCurveTo( x, y + k * this.topLeft[1], x + k * this.topLeft[0], y, x + this.topLeft[0], y ); ctx.closePath(); this._renderPaintInOrder(ctx);},setCoords: function () {this.callSuper('setCoords');this.set('topLeft', \[this.topLeft\[0\], this.topLeft\[1\]\]);this.set('topRight', \[this.topRight\[0\], this.topRight\[1\]\]);this.set('bottomLeft', \[this.bottomLeft\[0\], this.bottomLeft\[1\]\]);this.set('bottomRight', \[this.bottomRight\[0\], this.bottomRight\[1\]\]);},toObject: function (propertiesToInclude) {return fabric.util.object.extend(this.callSuper('toObject', propertiesToInclude), {topLeft: this.get('topLeft'),topRight: this.get('topRight'),bottomLeft: this.get('bottomLeft'),bottomRight: this.get('bottomRight'),});},toJSON: function (propertiesToInclude) {const data = this.callSuper('toJSON', propertiesToInclude);data.topLeft = this.get('topLeft');data.topRight = this.get('topRight');data.bottomLeft = this.get('bottomLeft');data.bottomRight = this.get('bottomRight');return data;},});// Register the class with Fabric.jsfabric.RoundedRect.async = true;// Define the fromObject methodfabric.RoundedRect.fromObject = function (object, callback) {return fabric.Object.\_fromObject('RoundedRect', object, callback);};
I'm trying to update the corner radius of this custom shape using the following function:
async function changeBorderRadius(value) {const canvas = canvasEditor.canvas;let activeObject = canvas.getActiveObject();if (projectStore.isTabGlobalOptions && !activeObject) {// If isTabGlobalOptions is true, apply the border radius to all tabscanvas.getObjects().forEach((obj) =\> {if (obj.id && obj.id.includes('tabs-rect') && obj.type === 'roundedRect') {if (obj.id.includes('verticle-tabs-rect')) {obj.set({topLeft: \[0, 0\],topRight: \[value, value\],bottomLeft: \[0, 0\],bottomRight: \[value, value\],});} else if (obj.id.includes('horizontal-tabs-rect')) {obj.set({topLeft: \[value, value\],topRight: \[value, value\],bottomLeft: \[0, 0\],bottomRight: \[0, 0\],});}obj.setCoords(); // Update the object's coordinates}});canvasEditor.\_reAdjustCanvasSizeForUpdate();canvas.requestRenderAll();await nextTick();} else {// If isTabGlobalOptions is false, apply the border radius only to the selected tabif (!activeObject ||!activeObject.id.includes('tabs-rect') ||activeObject.type !== 'roundedRect')return; if (activeObject.id.includes('verticle-tabs-rect')) { activeObject.set({ topLeft: [0, 0], topRight: [value, value], bottomLeft: [0, 0], bottomRight: [value, value], }); } else if (activeObject.id.includes('horizontal-tabs-rect')) { activeObject.set({ topLeft: [value, value], topRight: [value, value], bottomLeft: [0, 0], bottomRight: [0, 0], }); } activeObject.setCoords(); // Update the object's coordinates canvas.requestRenderAll(); await nextTick();}}
When I call this function, the updated radius value is correctly reflected in the JSON object (as confirmed by console logs), but the changes are not being reflected on the canvas. The shape on the canvas remains the same, without the updated corner radius.
when I resize the canvas using the below function, the changes gets reflected on the canvas:
_bindWheel() { this.canvas.on('mouse:wheel', function (this: fabric.Canvas, opt) { const delta = opt.e.deltaY; let zoom = this.getZoom(); zoom *= 0.999 ** delta; if (zoom > 20) zoom = 20; if (zoom < 0.01) zoom = 0.01; const center = this.getCenter(); this.zoomToPoint(new fabric.Point(center.left, center.top), zoom); opt.e.preventDefault(); opt.e.stopPropagation(); }); }
I've tried forcing a re-render of the canvas after updating the radius, but it didn't solve the issue. I'm not sure what I'm missing here. Any insights or suggestions would be greatly appreciated.Thank you in advance for your help!