2012-02-10 9 views
3

私はjavascriptで文字の正確なサイズを計算する必要があります。文字は、異なるフォントサイズやフォントファミリの属性などを持つことができます。JavaScriptのレターサイズを計算する

div要素を使用しようとしましたが、このメソッドは文字のサイズではなくdivのサイズのみを与えます。

<div style="display: inline; background-color: yellow; font-size: 53px; line-height:32px">A</div> 

誰でもこの問題の解決方法を知っていますか?

+0

この例では、フォントサイズを53ptsに設定します。なぜそれが画面上で異なるのでしょうか? –

+0

@Larry K、すべてのフォントがモノスペースではありません。文字「i」は、フォントファミリ、タイプ、カーニング及びその他の要因に応じて、文字「w」とは異なる境界矩形を決定する。 –

+0

あなたはどんな問題を解決しようとしていますか? – egrunin

答えて

4

これは基本的には一般的に不可能です。フォントカーニングは、オペレーティングシステム、ブラウザなどに応じて文字の可変幅が異なり、文字が互いに隣り合っていることに基づいています。 os +ブラウザに指定したフォントがない場合、フォントの置換が行われることがあります。

あなたが撮影しているより高いレベルのゴールで質問を再入力すると、あなたの問題に対する他のアプローチが提案される可能性があります。

+0

そのため、すべてのスタイルを適用した後に計算する必要があります。そして、システムがどのように「描く」かによって、サイズを知りたい。 – Max

3

@ Irongaze.comは、あなたのフォントが条件によっては実際のサイズが異なることが正しいです。

特定の文字のキャリブレーションを行う場合は、element.getBoundingClientRect()が有用な座標を与えると信じています。コントロールボックスとして使用するコンテナを完全にリセットしてください。異なるシステムで異なる結果を得るかもしれないことに注意してください。

jsFiddle

これはあなたの手紙の実際の目に見える部分が、それは判断し、コンテナのサイズの大きさを与えることはありませんのでご注意ください。たとえば、line-heightは、実際の文字サイズを変更することはありませんが、他の文字の配置に影響します。それに気をつけてください。

あなたが解決しようとしている問題について説明すると、それが役に立ちます。より良い解決策があるかもしれません。

+0

私はそれの価値を知らないので、私はラインハイトを使用することはできません。フォントサイズは動的に変更することができ、システムによって異なります。 – Max

+0

@Maxでは、element.getBoundingClientRect()を使用することを提案しました。ラインハイトは、正確な結果を得ることができない場合の反例でした。 –

0

他にも言及したように、これは直接測定することはできません。キャンバスに手紙を描き、どのピクセルが塗りつぶされているかを判断することができます。

ここにはdemo that does thisがあります。この機能は、次のとおりです。

/** 
* Draws a letter in the given font to an off-screen canvas and returns its 
* size as a {w, h, descenderH} object. 
* Results are cached. 
*/ 
function measureLetter(letter, fontStyle) { 
    var cacheKey = letter + ' ' + fontStyle; 
    var cache = measureLetter.cache; 
    if (!cache) { 
    measureLetter.cache = cache = {}; 
    } 
    var v = cache[cacheKey]; 
    if (v) return v; 

    // Create a reasonably large off-screen <canvas> 
    var cnv = document.createElement('canvas'); 
    cnv.width = '200'; 
    cnv.height = '200'; 

    // Draw the letter 
    var ctx = cnv.getContext('2d'); 
    ctx.fillStyle = 'black'; 
    ctx.font = fontStyle; 
    ctx.fillText(letter, 0.5, 100.5); 

    // See which pixels have been filled 
    var px = ctx.getImageData(0, 0, 200, 200).data; 
    var minX = 200, minY = 200, maxX = 0, maxY = 0; 
    var nonZero = 0; 
    for (var x = 0; x < 200; x++) { 
    for (var y = 0; y < 200; y++) { 
     var i = 4 * (x + 200 * y); 
     var c = px[i] + px[i + 1] + px[i + 2] + px[i + 3]; 
     if (c === 0) continue; 
     nonZero++; 
     minX = Math.min(x, minX); 
     minY = Math.min(y, minY); 
     maxX = Math.max(x, maxX); 
     maxY = Math.max(y, maxY); 
    } 
    } 

    var o = {w: maxX - minX, h: maxY - minY, descenderH: maxY - 100}; 
    cache[cacheKey] = o; 
    return o; 
} 

これはアンチエイリアスに対して敏感であることに注意してください。結果はピクセルによって外れることがあります。

+0

それはまた非常に遅いです。結果をキャッシュしない限り、このテクニックは使用しないでください。ページ上で数回だけ実行しています...しかし、非常にクールです。 :-) –

+0

この解決策には既にキャッシュが含まれているため、結果を自分でキャッシュすることは意味がありません。 – danvk

関連する問題