Tom
Tom

Reputation: 4652

Rect with stroke, the stroke line is mis-transformed when scaled

I have got a lot of helps from this site and contributors here, thanks. Now I have a question about the Rectangle in Fabric.js with stroke, as I used it as kind of placeholder for images and text, when I scaled it, the border line width is scaled too, I think it's kind a problem as I want to keep the border width not changed.

var canvas = new fabric.Canvas("c1");

var el = new fabric.Rect({
    originX: "left",
    originY: "top",
    left: 5,
    top: 5,
    stroke: "#ccc",
    strokWidth: 1,
    fill: 'transparent',
    opacity: 1,
    width: 200,
    height: 200,
    cornerSize: 6
});

canvas.add (el);
canvas.renderAll ();

See example here http://jsfiddle.net/9yb46/, try scale it horizontally. And a image is here too, and see the left border and right border width, supposed as same as top and bottom border, but not:

enter image description here

Upvotes: 7

Views: 8744

Answers (3)

Yara
Yara

Reputation: 41

Fabricjs now has a strokeUniform property on fabric.Rect that can be used to prevent the stroke width from mis-transforming.

When you set strokeUniform to false it will scale with the object if true it will match the pixel size of the stroke width.

var el = new fabric.Rect({
    originX: "left",
    originY: "top",
    left: 5,
    top: 5,
    stroke: "#ccc",
    strokWidth: 1,
    fill: 'transparent',
    opacity: 1,
    width: 200,
    height: 200,
    cornerSize: 6,
    strokeUniform: true
});

Upvotes: 3

Jesse
Jesse

Reputation: 1935

This can be done so that you can scale independently.

In the scaling event check the width, height and scale factors, set the height and width to the new effective values and reset the scaleX and scaleY.

This quite probably will break other things that are scaled with the object so you'd have to handle those attributes in a similar fashion.

Demo Fiddle.

var canvas = new fabric.Canvas("c1");

var el = new fabric.Rect({
    originX: "left",
    originY: "top",
    left: 5,
    top: 5,
    stroke: "rgb(0,0,0)",
    strokeWidth: 1,
    fill: 'transparent',
    opacity: 1,
    width: 200,
    height: 200,
    cornerSize: 6
});

el.on({
    'scaling': function(e) {
        var obj = this,
            w = obj.width * obj.scaleX,
            h = obj.height * obj.scaleY,
            s = obj.strokeWidth;

        obj.set({
            'height'     : h,
            'width'      : w,
            'scaleX'     : 1,
            'scaleY'     : 1
        });
    }
});

canvas.add (el);
canvas.renderAll ();

Upvotes: 10

arty
arty

Reputation: 1276

First of all you have miss-typed the name of the property in your fiddle : strokWidth - e is missing. But this is not the cause of the problem since the default value for the strokeWidth is 1.

The scaled stroke issue is the expected behavior and what you ask to do is not. Anyway, before you check my code, read here and here and maybe some more here.

Then try this code to help with your needs, this will work perfectly only if you keep the scale ratio of your rectangle as 1:1 (scaleX = scaleY).

This is jsfiddle:

var canvas = new fabric.Canvas("c1");

var el = new fabric.Rect({
    originX: "left",
    originY: "top",
    left: 5,
    top: 5,
    stroke: "rgb(0,0,0)",
    strokeWidth: 1,
    fill: 'transparent',
    opacity: 1,
    width: 200,
    height: 200,
    cornerSize: 6
});

el.myCustomOptionKeepStrokeWidth = 1;
canvas.on({
    'object:scaling': function(e) {
        var obj = e.target;
        if(obj.myCustomOptionKeepStrokeWidth){
            var newStrokeWidth = obj.myCustomOptionKeepStrokeWidth / ((obj.scaleX + obj.scaleY) / 2);
            obj.set('strokeWidth',newStrokeWidth);
        }
    }
});

canvas.add (el);
canvas.renderAll ();

Upvotes: 6

Related Questions