Fabricjs如何缩放对象但保持边框(笔触)宽度固定

时间:2016-09-17 15:50:44

标签: fabricjs

我正在开发一个基于fabricjs的图表工具。我们的工具有我们自己的形状集合,这是基于svg。我的问题是当我缩放对象时,边界(笔划)比例也是如此。我的问题是:如何缩放对象但保持笔划宽度固定。请检查附件 small version

scaled version

非常感谢!

4 个答案:

答案 0 :(得分:8)

这是一个简单的例子,在对象的比例上,我们保持对原始笔划的引用,并根据比例计算新的笔划。



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>
&#13;
&#13;
&#13;

答案 1 :(得分:5)

我发现了一种更好的解决方案,适用于SVG路径。

您可以覆盖fabricjs&#39; _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来调整边界框以解决尺寸差异。

此外,更完整的实现可能会添加一个结构对象属性,以有条件地控制这两个重写方法的更改。

答案 2 :(得分:1)

另一种方法是按比例绘制一个新对象并移除已缩放的对象。

const Bottleneck = require('bottleneck');

const main = () => {
    console.log('starting main');
    const limiter = new Bottleneck({
        maxConcurrent: 3,
        minTime: 100
    });

    const worker = (text, limiterCb) => {
        Promise.resolve()
        .then(() => {
            console.log(`starting ${text}`);
            let res;
            for (let i = 0; i < 10000000000; i++) {
                res++
            }
            console.log(`ending ${text}`);
            limiterCb();
        });
    };

    const limiterCb = res => console.log('limiter finished');

    limiter.submit(worker, 'hello', limiterCb);
    limiter.submit(worker, 'hello', limiterCb);
    limiter.submit(worker, 'hello', limiterCb);
    limiter.submit(worker, 'hello', limiterCb);
}

main();
console.log('exiting')

对我来说很完美。

答案 3 :(得分:0)

有一个名为的属性:strokeUniform 这样使用 shape.set({stroke:'#f55b76',strokeWidth:2,strokeUniform:true})