Javascript - 获取实际渲染的字体高度

标签 javascript html5-canvas font-size text-size

在我的即时编辑器工具中,我非常希望能够获得文本/字体的实际渲染高度 - (我的意思不是仅仅获取 CSS 字体大小,既不计算也不预设)。

这可以用 JavaScript 实现吗?

如果不是直接,是否可以像在 Canvas 中渲染字体一样以常规文本的方式渲染字体 - 然后找出答案?

编辑 - 我的“开发”解决方案:根据建议的链接,我构建了一些纯 JavaScript 代码,它遍历 Canvas 中的像素并分析像素是否为白色并起作用因此,它几乎不是代码的开发人员版本 - 只是输出一些有用的信息并显示如何访问计算数据 - http://jsfiddle.net/DV9Bw/1325/

HTML:

<canvas id="exampleSomePrettyRandomness" width="200" height="60"></canvas>
<div id="statusSomePrettyRandomness"></div>

JS:

function findPos(obj) {
var curleft = 0, curtop = 0;
if (obj.offsetParent) {
    do {
        curleft += obj.offsetLeft;
        curtop += obj.offsetTop;
    } while (obj = obj.offsetParent);
    return { x: curleft, y: curtop };  
}
return undefined;
}


var status = document.getElementById('statusSomePrettyRandomness');
var example = document.getElementById('exampleSomePrettyRandomness');
var context = example.getContext('2d');
context.fillStyle = "rgb(255,255,255)";
context.fillRect(0, 0, 200, 200);
context.fillStyle = "rgb(0,0,0)";
context.font = "30px Arial";
context.fillText("Hello World",0,30);
var pos = findPos(example);
var x = example.pageX - pos.x;
var y = example.pageY - pos.y;
var foundTop = false;
xPos = 0;
yPos = 0;
topY = -1;
bottomY = -1;
var fuse = 1000;
while( fuse-- > 0 ){
//status.innerHTML += yPos+"<br>";
if( yPos == (example.offsetHeight - 2) ){
    xPos++;
    yPos = 0;
    continue;
}
    var data = context.getImageData(xPos, yPos, 1, 1).data;
if( ! foundTop ){
    if( (data[0] != 255) && (data[1] != 255) && (data[2] != 255) ){
        topY = yPos;
        status.innerHTML += "<br>Found top: "+topY+" X:"+xPos+" Color: rgba("+data[0]+","+data[1]+","+data[2]+")"+"<br>";
        foundTop = true;
    }
} else {
    if( (data[0] == 255) && (data[1] == 255) && (data[2] == 255) ){
        bottomY = yPos;
        status.innerHTML += "<br>Found bottom: "+bottomY+" X:"+xPos+"<br>";
        break;
    }
} 
yPos++;
if( yPos > example.offsetHeight ){
    status.innerHTML += ""
        +"Y overflow ("+yPos+">"+example.offsetHeight+")"
        +" - moving X to "+xPos
        +" - reseting Y to "+yPos 
        +"<br>"
    ;
        xPos++; 
    yPos = 0;
}
}
status.innerHTML += "Fuse:"+fuse+", Top:"+topY+", Bottom: "+bottomY+"<br>";
status.innerHTML += "Font height should be: "+(bottomY-topY)+"<br>";

编辑2:为什么这不是重复的:我的问题实际上只是字体或字母的真实渲染高度,“possible duplicate ”是关于您需要多少空间打印文本,那里提供的答案无论如何都不能回答我的确切问题。

最佳答案

我不知道有任何方法可以返回文本的高度,例如 measureText (当前返回宽度)。

但是,理论上您可以简单地在 Canvas 上绘制文本,然后 trim the surrounding transparent pixels然后测量 Canvas 高度..

这是一个示例(高度将记录在控制台中):

// Create a blank canvas (by not filling a background color).
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');

// Fill it with some coloured text.. (black is default)
ctx.font = "48px serif";
ctx.textBaseline = "hanging";
ctx.fillText("Hello world", 0, 0);

// Remove the surrounding transparent pixels
// result is an actual canvas element
var result = trim(canvas);

// you could query it's width, draw it, etc..
document.body.appendChild(result);

// get the height of the trimmed area
console.log(result.height);

// Trim Canvas Pixels Method
// https://gist.github.com/remy/784508
function trim(c) {

  var ctx = c.getContext('2d'),

    // create a temporary canvas in which we will draw back the trimmed text
    copy = document.createElement('canvas').getContext('2d'),

    // Use the Canvas Image Data API, in order to get all the
    // underlying pixels data of that canvas. This will basically
    // return an array (Uint8ClampedArray) containing the data in the
    // RGBA order. Every 4 items represent one pixel.
    pixels = ctx.getImageData(0, 0, c.width, c.height),

    // total pixels
    l = pixels.data.length,
    
    // main loop counter and pixels coordinates
    i, x, y,

    // an object that will store the area that isn't transparent
    bound = { top: null, left: null, right: null, bottom: null };

  // for every pixel in there
  for (i = 0; i < l; i += 4) {

    // if the alpha value isn't ZERO (transparent pixel)
    if (pixels.data[i+3] !== 0) {

      // find it's coordinates
      x = (i / 4) % c.width;
      y = ~~((i / 4) / c.width);
  
      // store/update those coordinates
      // inside our bounding box Object

      if (bound.top === null) {
        bound.top = y;
      }
      
      if (bound.left === null) {
        bound.left = x; 
      } else if (x < bound.left) {
        bound.left = x;
      }
      
      if (bound.right === null) {
        bound.right = x; 
      } else if (bound.right < x) {
        bound.right = x;
      }
      
      if (bound.bottom === null) {
        bound.bottom = y;
      } else if (bound.bottom < y) {
        bound.bottom = y;
      }
    }
  }
  
  // actual height and width of the text
  // (the zone that is actually filled with pixels)
  var trimHeight = bound.bottom - bound.top,
      trimWidth = bound.right - bound.left,

      // get the zone (trimWidth x trimHeight) as an ImageData
      // (Uint8ClampedArray of pixels) from our canvas
      trimmed = ctx.getImageData(bound.left, bound.top, trimWidth, trimHeight);
  
  // Draw back the ImageData into the canvas
  copy.canvas.width = trimWidth;
  copy.canvas.height = trimHeight;
  copy.putImageData(trimmed, 0, 0);

  // return the canvas element
  return copy.canvas;
}
<canvas id="canvas"></canvas>

图像数据API:https://developer.mozilla.org/en-US/docs/Web/API/ImageData

关于Javascript - 获取实际渲染的字体高度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33777577/

相关文章:

javascript - Angular ng-repeat 中的 Json 字符串不起作用

javascript - 为什么 React 说 “Invalid prop ` Children`” 类型是对象而不是函数?

javascript - 如何在每次点击时添加一定数量?

html - 如何找到特定大小的特定字体的ex值

ios - 增加 textView 的文本大小会导致文本变小 | swift iOS

html - css中的字体大小中等

javascript - Ag网格垂直滚动问题

javascript - 在多个 Canvas 上默认禁用 imageSmoothingEnabled

javascript - 在 JavaScript Canvas 中绘制圆弧起点、半径和终点

javascript - canvas.toDataURLWithMultiplier 不是一个函数