简体   繁体   English

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

[英]Javascript - get actual rendered font height

In my on-the-fly editor tool I would really appreciate to get actual rendered height of the text / font - (I do not mean just getting CSS font-size, neither computed nor preset). 在我的即时编辑器工具中,我非常希望获得文本/字体的实际渲染高度-(我并不是说只获取CSS字体大小,既不计算也不预设)。

Is this achieveable in javascript? 在JavaScript中可以实现吗?

If not directly, is possible something as rendering font in canvas the same way as it is rendered as regular text - and then finding out? 如果不是直接的话,是否有可能像在画布中渲染字体一样,将其呈现为普通文本,然后找出来?

EDIT - my "dev" solution: Based on suggested links I've built a little pure-javascript code, that goes through pixels in canvas and analyses whether the pixel is white or not and acts accordingly, it is hardly a developer version of a code - just outputs few useful info and shows how to access computed data - http://jsfiddle.net/DV9Bw/1325/ 编辑-我的“开发”解决方案:根据建议的链接,我构建了一些纯JavaScript代码,该代码会遍历画布中的像素并分析像素是否为白色并相应地起作用,因此它几乎不是开发人员的版本代码-仅输出一些有用的信息并显示如何访问计算数据-http://jsfiddle.net/DV9Bw/1325/

HTML: HTML:

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

JS: 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>";

EDIT 2: Why this is not a duplicate: My question is about really just real rendered height of a font or a letter, " possible duplicate " is about how much space do you need to print a text, answers provided there don't answer my exact problem anyways. 编辑2:为什么这不是重复的:我的问题是关于字体或字母的实际渲染高度,“ 可能的重复 ”是关于打印文本需要多少空间,答案是没有答案反正我的确切问题。

I am not aware of any method that would return the height of a text such as measureText (which does currently return the width ). 我不知道有任何方法可以返回文本的height ,例如measureText (当前确实返回width )。

However, in theory you can simply draw your text in the canvas then trim the surrounding transparent pixels then measure the canvas height.. 但是,从理论上讲,您可以简单地在画布上绘制文本,然后修剪周围的透明像素,然后测量画布的高度。

Here is an example (the height will be logged in the console): 这是一个示例(高度将记录在控制台中):

 // 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> 

Image Data API: https://developer.mozilla.org/en-US/docs/Web/API/ImageData 图片数据API: https//developer.mozilla.org/zh-CN/docs/Web/API/ImageData

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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