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

跟風遠走 提交于 2019-11-26 23:21:41

问题


I'm developing a diagram tool based on fabricjs. Our tool has our own collection of shape, which is svg based. My problem is when I scale the object, the border (stroke) scale as well. My question is: How can I scale the object but keep the stroke width fixed. Please check the attachments.

Thank you very much!


回答1:


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>



回答2:


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.




回答3:


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.




回答4:


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



来源:https://stackoverflow.com/questions/39548747/fabricjs-how-to-scale-object-but-keep-the-border-stroke-width-fixed

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!