web-dev-qa-db-ja.com

背景付きのキャンバスにテキストを書き込む

キャンバスに画像を書き、背景付きのテキストを書くことは可能ですか?たとえば、次のようになります。

http://awesomescreenshot.com/09f1qf2213

20
rask

キャンバスでのテキストの仕組み

残念ながら、テキストメソッドで背景付きのテキストを作成することはできません。テキスト自体を塗りつぶすか、輪郭を描くだけです。

これは、必要に応じて、書体(フォント)のグリフが個々の形状またはパスに変換されるためです。この場合、背景はグリフ自体の内部(塗りつぶしを使用したときに表示される部分)になります。グリフが幾何学的位置を使用する以外に使用しているブラックボックス(グリフが収まる四角形)のレイヤーがないため、一種のブラックボックスとベアリングを用意する必要があります。

古いコンピュータシステムでは、ほとんどのフォントはバイナリフォントで、ピクセルを設定またはクリアします。背景をクリアするだけでなく、背景を用意することもできます。これは、デフォルトではベクターベースの書体には当てはまりません(ブラウザーはグリフジオメトリに直接アクセスできるため、この方法で背景を提供できます)。

カスタム背景の作成

背景を作成するには、まず、図形や画像などの他の手段を使用して背景を描く必要があります。

例:

ctx.fillRect(x, y, width, height);

または

ctx.drawImage(image, x, y  [, width, height]);

次に、テキストを上に描画します。

ctx.fillText('My text', x, y);

measureTextを使用してテキストの幅(将来的には高さ:上昇+下降)を確認し、それを基準として使用できます。

var width = ctx.measureText('My text').width; /// width in pixels

これをすべて関数でラップできます。ここでの機能は基本的なものですが、色や背景のパラメータ、パディングなどで拡張できます。

/// expand with color, background etc.
function drawTextBG(ctx, txt, font, x, y) {

    /// lets save current state as we make a lot of changes        
    ctx.save();

    /// set font
    ctx.font = font;

    /// draw text from top - makes life easier at the moment
    ctx.textBaseline = 'top';

    /// color for background
    ctx.fillStyle = '#f50';

    /// get width of text
    var width = ctx.measureText(txt).width;

    /// draw background rect assuming height of font
    ctx.fillRect(x, y, width, parseInt(font, 10));

    /// text color
    ctx.fillStyle = '#000';

    /// draw text on top
    ctx.fillText(txt, x, y);

    /// restore original state
    ctx.restore();
}

ここでオンラインデモ

この「高さを測定する」方法は正確ではないことに注意してください。一時的なdiv/span要素を使用してフォントの高さを測定し、フォントとテキストが設定されている場合は、そこから計算されたスタイルを取得できます。

40
user1693593

より簡単な解決策は、fillTextを2回呼び出すことです。最初に、背景色を使用してテキストと同じ長さを繰り返す黒い長方形であるUnicode + 2588█の文字列。次に、通常どおり前景色を使ってfillTextを呼び出します。

4
ToonTalk

この関数は、垂直および水平方向に中央揃えのテキストと背景を提供します。等幅フォント(同じ幅の文字)でのみ機能します。関数は、印刷する文字列の文字数をカウントし、それらに0.62を掛けます(フォントの幅が高さの0.62倍より少し小さいと想定)。背景は、フォントサイズの1.5倍です。必要に応じてこれを変更してください。

function centeredText(string, fontSize, color) {
        var i = string.length;
        i = i*fontSize*0.62;
        if (i > canvas.width) {
          i = canvas.width;
        }
        ctx.fillStyle = "RGBA(255, 255, 255, 0.8)";
        ctx.fillRect(canvas.width / 2 - i / 2,canvas.height / 2 - (fontSize * 1.5) / 2, i, (fontSize * 1.5) );
        ctx.font = fontSize.toString() + "px monospace";
        ctx.fillStyle = color;
        ctx.textBaseline = "middle";
        ctx.textAlign = "center";

        ctx.fillText(string, canvas.width / 2, canvas.height / 2);
    }

したがって、関数の呼び出しは次のようになります。

centeredText("Hello World", 30, "red");
0
Olof