admin管理员组

文章数量:1289346

I'm using fabric.js. I would like to get the dimensions of the rectangle (is "bounding box" the correct term?) that exactly contains the text (represented by the red box below). The default fabric.js box has padding even if I change padding to 0.

I tried to get the context from the fabric canvas and then call .measureText() but it didn't give the full information I needed for a bounding box.

EDIT:

It seems there are several ponents of the IText object: the container, the selection area, and the text itself. In the image below, the IText box is the light blue line. The selection area is the light blue fill. The red box is what I need....it's the area that exactly contains the text itself (not even 1 pixel between such a rectangle and the most extreme parts of the text). The methods getBoundingRectHeight and getBoundingRectWidth (both deprecated and replaced by getBoundingRect I believe) return the height/width of the outer IText container box (light blue line).

Note: this is an 8 px padded box (the area between the blue line and blue fill). Even if I make padding 0, the functions still don't give me what I need.

I'm using fabric.js. I would like to get the dimensions of the rectangle (is "bounding box" the correct term?) that exactly contains the text (represented by the red box below). The default fabric.js box has padding even if I change padding to 0.

I tried to get the context from the fabric canvas and then call .measureText() but it didn't give the full information I needed for a bounding box.

EDIT:

It seems there are several ponents of the IText object: the container, the selection area, and the text itself. In the image below, the IText box is the light blue line. The selection area is the light blue fill. The red box is what I need....it's the area that exactly contains the text itself (not even 1 pixel between such a rectangle and the most extreme parts of the text). The methods getBoundingRectHeight and getBoundingRectWidth (both deprecated and replaced by getBoundingRect I believe) return the height/width of the outer IText container box (light blue line).

Note: this is an 8 px padded box (the area between the blue line and blue fill). Even if I make padding 0, the functions still don't give me what I need.

Share Improve this question edited Oct 4, 2015 at 5:23 jbobbins asked Oct 2, 2015 at 22:47 jbobbinsjbobbins 1,2914 gold badges18 silver badges28 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 4

I have no idea about the performance or resources that are used to do this. But it does work. Thanks to @Prestaul's post for a getting me started. This is what I came up with:

function getBoundingBox(ctx, left, top, width, height) {
    var ret = {};

    // Get the pixel data from the canvas
    var data = ctx.getImageData(left, top, width, height).data;
    console.log(data);
    var first = false; 
    var last = false;
    var right = false;
    var left = false;
    var r = height;
    var w = 0;
    var c = 0;
    var d = 0;

    // 1. get bottom
    while(!last && r) {
        r--;
        for(c = 0; c < width; c++) {
            if(data[r * width * 4 + c * 4 + 3]) {
                console.log('last', r);
                last = r+1;
                ret.bottom = r+1;
                break;
            }
        }
    }

    // 2. get top
    r = 0;
    var checks = [];
    while(!first && r < last) {

        for(c = 0; c < width; c++) {
            if(data[r * width * 4 + c * 4 + 3]) {
                console.log('first', r);
                first = r-1;
                ret.top = r-1;
                ret.height = last - first - 1;
                break;
            }
        }
        r++;
    }

    // 3. get right
    c = width;
    while(!right && c) {
        c--;
        for(r = 0; r < height; r++) {
            if(data[r * width * 4 + c * 4 + 3]) {
                console.log('last', r);
                right = c+1;
                ret.right = c+1;
                break;
            }
        }
    }

    // 4. get left
    c = 0;
    while(!left && c < right) {

        for(r = 0; r < height; r++) {
            if(data[r * width * 4 + c * 4 + 3]) {
                console.log('left', c-1);
                left = c;
                ret.left = c;
                ret.width = right - left - 1;
                break;
            }
        }
        c++;

        // If we've got it then return the height
        if(left) {
            return ret;    
        }
    }

    // We screwed something up...  What do you expect from free code?
    return false;
}

And here's a jsfiddle demo: http://jsfiddle/spencerw/j41jx0e2/

Have you tried getBoundingRectHeight() and getBoundingRectWidth() methods available on every fabric object ?

The following is an excerpt from "HTML Canvas 2D Context, Editor's Draft 13 November 2014" of W3C. It's a note from the chapter on drawing text:

Glyphs rendered using fillText() and strokeText() can spill out of the box given by the font size (the em square size) and the width returned by measureText() (the text width). This version of the specification does not provide a way to obtain the bounding box dimensions of the text. If the text is to be rendered and removed, care needs to be taken to replace the entire area of the canvas that the clipping region covers, not just the box given by the em square height and measured text width.

Currently, it seems you cannot determine a bounding box from javascript like you need. You can only rely on redrawing the whole canvas / clipping region.

本文标签: javascriptFabricjs Get text bounding box width and heightStack Overflow