web-dev-qa-db-ja.com

Fabricjsオブジェクトを拡大縮小するが、境界線(ストローク)の幅を固定する方法

私はfabricjsに基づいたダイアグラムツールを開発しています。私たちのツールには、svgベースの独自の形状コレクションがあります。私の問題は、オブジェクトを拡大縮小するときに、境界線(ストローク)も拡大縮小することです。私の質問は、オブジェクトを拡大縮小し、ストローク幅を固定したままにするにはどうすればよいですか。添付ファイルを確認してください。
small version

scaled version

どうもありがとうございました!

11
trongd

これは、オブジェクトの縮尺で元のストロークへの参照を保持し、縮尺に基づいて新しいストロークを計算する簡単な例です。

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>
9
StefanHayden

私は、さらに優れたソリューションのように感じられ、SVGパスで非常にうまく機能することを発見しました。

以下に示すように、fabricjsの__renderStroke_メソッドをオーバーライドし、ctx.scale(1 / this.scaleX, 1 / this.scaleY);の前にctx.stroke();を追加できます。

_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();
};
_

サイズの違いを考慮してバウンディングボックスを調整するには、_fabric.Object.prototype._getTransformedDimensions_をオーバーライドする必要がある場合もあります。

また、より完全な実装では、ファブリックオブジェクトプロパティを追加して、オーバーライドされた両方のメソッドのこの変更を条件付きで制御することもできます。

7
byoungb

次のプロパティがあります:strokeUniformこのように使用しますshape.set({stroke: '#f55b76'、strokeWidth:2、strokeUniform:true})

3
Lonelydatum

別の方法は、スケーリングされたオブジェクトに新しいオブジェクトを描画し、スケーリングされたオブジェクトを削除することです。

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 ...);
    }
});    

私にぴったりです。

1
Dario