2015-11-18 50 views
2

在我的動態編輯器工具中,我真的很感謝獲得文本/字體的實際渲染高度 - (我並不是說只需獲取CSS字體大小,既不計算也不預設)。Javascript - 獲取實際渲染字體高度

這是可以在javascript中實現嗎?

如果不是直接的話,那麼可能會像在呈現爲普通文本時一樣呈現畫布中的字體 - 然後找出?

編輯 - 我的「開發」的解決方案:根據建議的鏈接我已經建立了一個小純JavaScript代碼,在畫布上經過像素和分析像素是白色或不和採取相應的行動,它是很難的代碼開發者版本 - 只是少數輸出有用的信息,並說明如何訪問計算數據 - 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」大概是多少空間,你需要打印文本,答案只要無論如何,請不要回答我確切的問題。

+0

我不知道我完成當你得到你的問題,並且我很忙,但是因爲你標記了你的問題[html5-canvas]也許[這個問題](http://stackoverflow.com/q/17627893/3702797),它的答案可以幫助你。 – Kaiido

+0

我標記它,因爲我猜可能有一個解決方案,繪製字體的方式與其作爲文本呈現方式相同 - 但在畫布中,作爲圖像像素 - 那麼我想我可以分析某種程度上的畫布像素,因爲我知道什麼是底色和淹沒字體的顏色是什麼:)現在更清楚了嗎? –

+1

也許試試這種方法? http://stackoverflow.com/questions/1134586/how-can-you-find-the-height-of-text-on-an-html-canvas –

回答

4

我不知道有任何方法可以返回文本的height,如measureText(目前返回width)。

然而,理論上你可以簡單地繪製文本在畫布上,然後trim the surrounding transparent pixels然後測量畫布高度..

下面是一個例子(高度將在控制檯登錄):

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

+0

我真的不需要寬度 - 所有我需要的是高度:) –

+0

@ jave.web我已經更新了我的答案,包括一個工作示例。 – Pierre

+0

謝謝,測試過,手動測量 - 工作。但我真的不明白代碼的作用 - 會不會很好,並且有點評論? :) –