Fabricjs How to scale object but keep the border (stroke) width fixed

There is a property called: strokeUniform Use it like this shape.set({stroke: '#f55b76', strokeWidth:2, strokeUniform: true })


I have found what feels like an even better solution, works really well with SVG paths.

You can override fabricjs' _renderStroke method and add ctx.scale(1 / this.scaleX, 1 / this.scaleY); before ctx.stroke(); as shown below.

fabric.Object.prototype._renderStroke = function(ctx) {
    if (!this.stroke || this.strokeWidth === 0) {
        return;
    }
    if (this.shadow && !this.shadow.affectStroke) {
        this._removeShadow(ctx);
    }
    ctx.save();
    ctx.scale(1 / this.scaleX, 1 / this.scaleY);
    this._setLineDash(ctx, this.strokeDashArray, this._renderDashedStroke);
    this._applyPatternGradientTransform(ctx, this.stroke);
    ctx.stroke();
    ctx.restore();
};

You may also need to override fabric.Object.prototype._getTransformedDimensions to adjust the bounding box to account for the difference in size.

Also a more complete implementation would probably add a fabric object property to conditionally control this change for both overridden methods.


Another way is to draw a new object on scaled and remove the scaled one.

object.on({
    scaled: function()
    {
        // store new widht and height
        var new_width = this.getScaledWidth();
        var new_height = this.getScaledHeight();

        // remove object from canvas
        canvas.remove(this);

        // add new object with same size and original options like strokeWidth
        canvas.add(new ...);
    }
});    

Works perfect for me.


Here is an easy example where on scale of an object we keep a reference to the original stroke and calculate a new stroke based on the scale.

var canvas = new fabric.Canvas('c', { selection: false, preserveObjectStacking:true });
window.canvas = canvas;
canvas.add(new fabric.Rect({ 
  left: 100, 
  top: 100, 
  width: 50, 
  height: 50, 
  fill: '#faa', 
  originX: 'left', 
  originY: 'top',
  stroke: "#000",
  strokeWidth: 1,
  centeredRotation: true
}));

canvas.on('object:scaling', (e) => {
	var o = e.target;
	if (!o.strokeWidthUnscaled && o.strokeWidth) {
  	o.strokeWidthUnscaled = o.strokeWidth;
  }
	if (o.strokeWidthUnscaled) {
  	o.strokeWidth = o.strokeWidthUnscaled / o.scaleX;
  }
})
canvas {
    border: 1px solid #ccc;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.6.4/fabric.min.js"></script>
<canvas id="c" width="600" height="600"></canvas>

Tags:

Fabricjs