0

我正在使用画布,我想不出任何解决方案,或者在网上找到我的问题的答案。

我有一个字体,其中包含不同大小的符号\字符 - 高度和宽度。

我想从字体中绘制一些字符(符号),并在符号的顶部\向下绘制一些字符。问题是我无法找到一种方法来获得我正在绘制的字符的确切高度(以像素为单位),并且它会导致中心符号与 top\down 之间的不需要的空格(用于获取一个字符串有函数 context.measureText(theText) )。

例如。假设我希望“X”成为我的中心符号。和 '-' 位于顶部。它看起来像这样

-
x

但现在“X”和“-”之间有我不想要的空间。

谁能帮我这个 ?

谢谢

4

3 回答 3

6

宽度很简单:画布的上下文有一个用于测量文本宽度的内置指标。

// this will measure text width
context.font = '14pt Verdana';
var m=context.measureText(yourText);
var theWidth=m.width;

高度比较困难,因为 measureText 不计算高度。

您通常可以使用字体大小来近似高度 - 这就是我所做的。

但是,如果您真的需要更高的准确性,这里有一个检查文本像素以计算其高度的函数:

function measureTextHeight(fontSizeFace) {

    // create a temp canvas
    var width=1000;
    var height=60;
    var canvas=document.createElement("canvas");
    canvas.width=width;
    canvas.height=height;
    var ctx=canvas.getContext("2d");

    // Draw the entire a-z/A-Z alphabet in the canvas
    var text="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    ctx.save();
    ctx.font=fontSizeFace;
    ctx.clearRect(0,0,width,height);
    ctx.fillText(text, 0, 40);
    ctx.restore();

    // Get the pixel data from the canvas
    var data = ctx.getImageData(0,0,width,height).data,
        first = false, 
        last = false,
        r = height,
        c = 0;

    // Find the last line with a non-transparent pixel
    while(!last && r) {
        r--;
        for(c = 0; c < width; c++) {
            if(data[r * width * 4 + c * 4 + 3]) {
                last = r;
                break;
            }
        }
    }

    // Find the first line with a non-transparent pixel
    while(r) {
        r--;
        for(c = 0; c < width; c++) {
            if(data[r * width * 4 + c * 4 + 3]) {
                first = r;
                break;
            }
        }

        // If we've got it then return the height
        if(first != r) return last - first;
    }

    // error condition if we get here
    return 0;
}
于 2013-05-29T21:04:54.133 回答
1

只是建立在以前的好答案的基础上。这将给出高度和宽度(我对一些 unicode 字符和 measureText 有一些问题,这是某些字符的唯一解决方案)。

function measureTextHeight(fontSizeFace, text) {
  var width = 1500;
  var height = 500;

  var canvas = document.createElement("canvas");
  canvas.width = width;
  canvas.height = height;
  var ctx=canvas.getContext("2d");
  ctx.save();
  ctx.font=fontSizeFace;
  ctx.clearRect(0,0,width,height);
  ctx.fillText(text, parseInt(width * 0.1, 10), parseInt(height / 2, 10));
  ctx.restore();
  document.body.appendChild(canvas);
  var data = ctx.getImageData(0,0,width,height).data;


  var topMost = false;
  var bottomMost = false;
  var leftMost = false;
  var rightMost = false;
  for(var x=0; x<width; x++) {
    for(var y=0; (y<height) && (!leftMost); y++) {
      //console.log("x: %s y: %s index: %s", x,y, getAlphaIndexForCoordinates(x,y,width,height).toString() );
      if(data[getAlphaIndexForCoordinates(x,y,width,height)] != 0) {
        leftMost = x;
      }
    }
  }
  for(var y=0; y<height; y++) {
    for(var x=0; (x<width) && (!topMost); x++) {
      //console.log("x: %s y: %s index: %s", x,y, getAlphaIndexForCoordinates(x,y,width,height).toString() );
      if(data[getAlphaIndexForCoordinates(x,y,width,height)] != 0) {
        topMost = y;
      }
    }
  }
  for(var x=width-1; x>=0; x--) {
    for(var y=height-1; (y>=0) && (!rightMost); y--) {
      //console.log("x: %s y: %s index: %s", x,y, getAlphaIndexForCoordinates(x,y,width,height).toString() );
      if(data[getAlphaIndexForCoordinates(x,y,width,height)] != 0) {
        rightMost = x;
      }
    }
  }
  for(var y=height-1; y>=0; y--) {
    for(var x=width-1; (x>=0) && (!bottomMost); x--) {
      //console.log("x: %s y: %s index: %s", x,y, getAlphaIndexForCoordinates(x,y,width,height).toString() );
      if(data[getAlphaIndexForCoordinates(x,y,width,height)] != 0) {
        bottomMost = y;
      }
    }
  }
  return ({
     width: (rightMost - leftMost) + 1
    ,height: (bottomMost - topMost) + 1
  });
}
function getAlphaIndexForCoordinates(x,y,width,height) {
  return (((width*4*y)+4*x)+3);
}
于 2014-11-07T00:57:13.547 回答
0

好的,很好地尝试了这段代码,我不得不对其进行一些更改以使其正常工作。

这是我们找到最后一行不透明像素后的代码。

所以万一有人需要它。只需更换享受。

    var blnFound = false;
    var intCurrRow = 0;

    // Find the first line with a non-transparent pixel
    while(!blnFound && intCurrRow < last) 
    {
      for(intCurrCol = 0; intCurrCol < width; intCurrCol++) 
      {
        var intCurrDataIdx = intCurrRow * width * 4 + intCurrCol * 4 + 3;
        if(data[intCurrDataIdx]) 
        {
          first = intCurrRow;
          blnFound = true;
          break;
        }
     }

     // If we've got it then return the height
     if (blnFound)
     {
       return last - first;
     }

     intCurrRow++;
   }
于 2013-06-03T15:13:00.330 回答