Trevor Windham
Trevor Windham

Reputation: 21

Aligning a fabric.js object to the top left corner of the inner text of an IText element

http://jsfiddle.net/541ev5nh/15/

I'm attempting to align the red Text object to the upper-left corner of the black IText object. When the Itext object is not rotated (at angle 0), you can see that the text is correctly aligned. However, rotating the IText throws the alignment off.

Resizing or changing the text of the IText also throws off the alignment, but don't worry about that for now. The rotation is the only thing that needs to work right now.

The problem is obviously coming from the fact that I'm using magic numbers to align the two items. I need a formulaic way derive these numbers that will keep the alignment consistent when the IText is rotated. Any ideas?

HTML:

<canvas id="canvas" width="800" height="600" style=""></canvas>

Javascript:

var w = 800;
var h = 600;
var cx = w/2;
var cy = h/2;

var auto = false; // auto/manual rotation

// Main "Text"
var txt = "Text";
var canvas = new fabric.Canvas('canvas');
var text = new fabric.IText(txt, { 
    left: 20, 
    top: 30, 
    fontFamily: 'sans-serif',
    fontSize: 80
});
canvas.add(text);
var pt = new fabric.Point(cx,cy);
text.setPositionByOrigin(pt, 'center', 'center');
canvas.setActiveObject(text);


// decorator
var txt = "Top left";
var deco = new fabric.Text(txt, { 
    left: 20, 
    top: 30, 
    fontFamily: 'sans-serif',
    fontSize: 14,
    stroke: '#DD0000',
    fill: '#DD0000'
});
canvas.add(deco);


canvas.on('object:modified', onModified);

function onModified(data){
    var rotatedPoint = data.target.getPointByOrigin("left", "top");
    deco.rotate(data.target.angle);
    deco.setPositionByOrigin(new fabric.Point(rotatedPoint.x + 1, rotatedPoint.y + 11), 'left', 'top');
    canvas.renderAll();
}

var angle = -2;

if (auto){
    setInterval(onInterval, 30);
}
else{
    onInterval();
    text.setCoords();
}

function onInterval(){
    angle += 2;
    text.rotate(angle);
    var data = {
        target: text
    };
    onModified (data);
}

Upvotes: 2

Views: 4880

Answers (1)

Mahbubur Rahman Manik
Mahbubur Rahman Manik

Reputation: 5161

You can achieve this by making objects group. Fabric has a nice support for object group.
See here:

// Main "Text"
    var txt = "Text";
    var canvas = new fabric.Canvas('canvas');
    canvas.clear();
    var text = new fabric.IText(txt, {     
        fontFamily: 'sans-serif',
        fontSize: 80
    });
    // decorator
    var txt = "Top left";
    var deco = new fabric.Text(txt, {  
        top:10,
        fontFamily: 'sans-serif',
        fontSize: 14,
        stroke: '#DD0000',
        fill: '#DD0000'
    });

    var group = new fabric.Group([ text, deco ], {  
      angle: 0
    });

    var lefts=canvas.getWidth()/2-group.getWidth()/2;
    var tops=canvas.getHeight()/2-group.getHeight()/2;
      group.set({
        'left':lefts,
        'top':tops
      });
    canvas.add(group);
    canvas.renderAll();

See in Fiddler

Upvotes: 1

Related Questions