2012-04-11 12 views
12

イメージの上にHTML5キャンバス内のテキストを描画しています(memeジェネレータ)。文字列がキャンバスの幅全体に広がるようにフォントサイズを計算したいと思います。HTML5キャンバス内の文字列の幅を決定する

基本的には、特定のフォントの文字列に対して、どのようなフォントサイズを使用するべきかをJavaScriptで判断する方法がありますか?

答えて

26

fillText()メソッドには、文字列をレンダリングする最大幅のオプションの第4引数があります。 MDNのマニュアルは言う

...

のmaxWidth

オプション。描画する最大幅。指定され、文字列がこの幅より広いと計算された である場合、フォントは より多く水平に凝縮されたフォントを使用するように調整されます(利用可能な場合、または が現在のフォントを水平方向に)またはそれより小さいフォント。

しかし、執筆の時点で、この引数は、それをレンダリングすることなく、文字列の大きさを決定するために​​を使用して第二の溶液につながるだけでなく、クロスブラウザは、サポートされていません。ここで

var width = ctx.measureText(text).width; 

var canvas = document.getElementById('canvas'), 
    ctx = canvas.getContext('2d'); 

// Font sizes must be in descending order. You may need to use `sort()` 
// if you can't guarantee this, e.g. user input. 
var fontSizes = [72, 36, 28, 14, 12, 10, 5, 2], 
    text = 'Measure me!'; 

// Default styles. 
ctx.textBaseline = 'top'; 
ctx.fillStyle = 'blue'; 

var textDimensions, 
    i = 0; 

do { 
    ctx.font = fontSizes[i++] + 'px Arial'; 
    textDimensions = ctx.measureText(text);   
} while (textDimensions.width >= canvas.width); 

ctx.fillText(text, (canvas.width - textDimensions.width)/2, 10);​ 

jsFiddle ...私はそれを行うことができます方法です。

私はフォントサイズのリストを降順に並べ、リストを繰り返して、レンダリングされたテキストがキャンバスの寸法に収まるかどうかを判断します。

もしそうなら、私はテキストの中心を揃えます。テキストの左右にパディングが必要な場合は、テキストが収まるかどうかを計算するときに、パディング値をtextDimensions.widthに追加します。

フォントサイズのリストが長い場合は、binary search algorithmを使用する方がよいでしょう。ただし、コードの複雑さは増します。

たとえば、フォントサイズが200の場合、配列要素の線形反復はO(n)になります。

バイナリチョップはO(log n)にする必要があります。

ここには、機能のの勇気があります。

var textWidth = (function me(fontSizes, min, max) { 

    var index = Math.floor((min + max)/2); 

    ctx.font = fontSizes[index] + 'px Arial'; 

    var textWidth = ctx.measureText(text).width; 

    if (min > max) { 
     return textWidth; 
    } 

    if (textWidth > canvas.width) { 
     return me(fontSizes, min, index - 1); 
    } else { 
     return me(fontSizes, index + 1, max); 
    } 

})(fontSizes, 0, fontSizes.length - 1); 

jsFiddle

+1

リンクによって比例サイズを計算します。 – Phrogz

+0

@Phrogz更新された回答を確認してください。 :) – alex

+0

私はあなたが90k + repを得ることができないことを知っていたはずです。 :) 非常に素晴らしい。 – Phrogz

0

私は次のコードを持っています。多少のエラーがあるかもしれませんが、フォントサイズのリストは必要ありません。私は、フォントサイズと幅を取得し、それが大きすぎる場合、私はいいかもしれないキャンバスの幅とパディングのドキュメントおよび/またはサンプルコードに(50)

ctx.font = FONT_SIZE+"pt Verdana"; 
var textWidth = ctx.measureText(markText).width; 
if(textWidth > canvas.width - 50) { 
    ctx.font = parseInt(FONT_SIZE*(canvas.width-50)/textWidth)+"pt Verdana"; 
    textWidth = ctx.measureText(markText).width; 
} 
ctx.textBaseline = "middle"; 
ctx.fillStyle = "rgba(255,255,255,0.5)"; 
ctx.strokeStyle = "rgba(0,0,0,0.5)"; 
var xT = image.width/2 - textWidth/2; 
var yT = image.height/2; 
ctx.fillText(markText, xT, yT); 
ctx.strokeText(markText, xT, yT); 
関連する問題