简体   繁体   中英

Fabric.js: Get text bounding box width and height

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 components 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.

您是否尝试过在每个结构对象上使用getBoundingRectHeight()getBoundingRectWidth()方法?

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.net/spencerw/j41jx0e2/

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM