15

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

基本的に、特定の幅の特定のフォントの文字列に使用するフォントサイズをJavaScriptで決定する方法はありますか?

4

3 に答える 3

32

fillText()メソッドにはオプションの 4 番目の引数があり、これは文字列をレンダリングする最大幅です。

MDN のドキュメントには次のように書かれています...

最大幅

オプション。描画する最大幅。指定されていて、文字列がこの幅よりも広く計算されている場合、フォントは、より水平方向に圧縮されたフォントを使用するように調整されます (使用可能な場合、または現在のフォントを水平方向に拡大縮小することによって合理的に読みやすいフォントを合成できる場合)。フォント。

ただし、執筆時点では、この引数はクロス ブラウザーで十分にサポートされていないためmeasureText()、レンダリングせずに文字列のサイズを決定するために使用する 2 番目のソリューションにつながります。

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テキストが収まるかどうかを計算するときにパディング値を に追加します。

試すべきフォント サイズの長いリストがある場合は、二分探索アルゴリズムを使用することをお勧めします。ただし、これによりコードが複雑になります。

たとえば、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 .

于 2012-04-11T03:01:20.933 に答える