如何计算动态画布上文本对象的边界框

时间:2017-03-19 00:16:38

标签: javascript html5 canvas html5-canvas fabricjs

我正在尝试计算html画布上文本对象的像素高度和宽度。我已经尝试了下面看到的一些代码,但我的结果却是错误的。有更清洁的方法来计算这个吗?动态画布需要根据匹配文本的长度和大小进行调整。

  1. px高度和宽度需要正确计算。左上角最像素到最右下角的像素。
  2. 画布需要调整大小以最小化计算时间并考虑文本金额,包括" \ n" s。我试过
  3. canvas.setWidth(400 + text.getBoundingRectWidth()); canvas.setHeight(400 + text.getBoundingRectHeight());

    但我不确定它是否有效。

    如何重写此代码以使画布大小变为动态并调整为可以更改的文本(例如,在textarea中撰写文章的人)?

    如何正确计算文字大小?

    如果有人重写此代码以符合我上面的规范,我可以提供奖励(金钱,礼品卡,免费披萨等......)。我花了很多时间试图解决这个问题。

    研究性: Calculate bounding box of arbitrary pixel-based drawing 看起来很有希望。

    这是JSBIN(基于Fabric.js: Get text bounding box width and heighthttp://jsbin.com/zoqolik/3/edit?html,css,js,console,output

    fabric.Object.prototype.objectCaching = false;
    var txt = '\n'+'Adklfmask'+'\n'+'asdfsd'+'\n'+'asdfsd'+'\n'+'asdfsd'+"\n";
    
    
    var canvas = new fabric.Canvas('canvas');
    var text = new fabric.IText(txt, { 
        left: 200, 
        top: 200, 
        fontFamily: 'Princess Sofia',
        padding: 5,
        fontSize: 35,
        lineHeight: 2.5,
        textAlign: 'center'
    });
    
    canvas.add(text);
    canvas.renderAll();
    
    var ctx = canvas.getContext();
    
    var hei = Math.ceil(300+text.getBoundingRectHeight());
    var wid = Math.ceil(300+text.getBoundingRectWidth());
    
    function setWidth(width) {
      var canvas = document.getElementById("canvas");  
      canvas.width = width;
    }
    function setHeight(height) {
      var canvas = document.getElementById("canvas");  
      canvas.height = height;
    }
    canvas.setWidth(400+text.getBoundingRectWidth());
    canvas.setHeight(400+text.getBoundingRectHeight());
    
    // get/draw bounding box
    var bbox = getBoundingBox(ctx, 0, 0, wid, hei);
    console.log(bbox.width + ' x ' + bbox.height);
    drawBoundingBox(ctx, bbox);
    
    
    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('right', c);
                    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;
    }
    

1 个答案:

答案 0 :(得分:-1)

而不是

canvas.setWidth(400+text.getBoundingRectWidth());
canvas.setHeight(400+text.getBoundingRectHeight());

使用

var textSize = ctx.measureText(text);
canvas.setWidth(400+textSize.width);
canvas.setHeight(400+textSize.height);