CanvasDOM画像処理

【JavaScript】 Canvas上のテキストの幅と高さを求める

更新日:2024/04/22

Canvas上で文字列の幅と高さを求め、枠を描画するところまでやってみます。

 

文字列の幅と高さを計算

Canvas上での文字列の幅と高さは、コンテキストのmeasureText()メソッドを使用します。

measureText()メソッドは幅を取得するケースが多いですが、高さも取得できます。

measureText()メソッド

文字列を指定すると、文字列の枠情報を取得できます。

JavaScript:measureText使用例

const cvs = document.getElementById("canvas");
const context = cvs.getContext("2d");

const text = "文字列の幅と高さを取得";

const measure = context.measureText( text );

measureText()から返る値はTextMetricsオブジェクトで、次のプロパティを持っています。

TextMetricsオブジェクト {
    width : 文字列の幅 ,
    actualBoundingBoxLeft : 基準点から左枠までの距離
    actualBoundingBoxRight  : 基準点から右枠までの距離
    actualBoundingBoxAscent : 基準点から上枠までの距離
    actualBoundingBoxDescent  : 基準点から下枠までの距離
}

基準点は、textBaselinetextAlignにより設定されます。

幅はwidthで取得できます。
actualBoundingBoxLeftactualBoundingBoxRightからも求めることができますが、widthとイコールにはなりません。

高さは、actualBoundingBoxAscentactualBoundingBoxDescentの合計から求めることができます。

JavaScript:文字列の高さと幅を求める例

const measure = context.measureText( text );

const  textWidth =  measure.width,
const  textHeight =  measure.actualBoundingBoxAscent 
                               + measure.actualBoundingBoxDescent

 

文字列の矩形を計算

文字列の矩形は、次の計算式で求めることができます。

なおfillText()strokeText()で指定した座標を( mx , my )とします。

左上座標( x , y )

const x = mx - Math.abs( measure.actualBoundingBoxLeft )

const y = my -  measure.actualBoundingBoxAscent

Math.abs()は絶対値を求めるメソッドです。

actualBoundingBoxLeftは、Google Chromeではプラスの値になりますが、Firefoxではマイナスの値になります。
そのためMath.abs()は絶対値を求めてから、マイナスしています。

幅width,高さheight

幅と高さは、前項と同じです。

const width = measure.width

const height = measure.actualBoundingBoxAscent 
                + measure.actualBoundingBoxDescent

文字枠矩形を描画

textAlignとtextBaselineの変化に合わせて、文字列枠を描画してみます。

(()=>{
        const lineDraw = (cts, sx , sy , ex , ey ) =>{
            cts.beginPath();
            cts.strokeStyle = "aqua";
            cts.moveTo( sx  , sy );
            cts.lineTo( ex  , ey );
            cts.stroke();
        };
        window.addEventListener( "DOMContentLoaded" , ()=> {

            const cvs = document.getElementById("canvas");
            const context = cvs.getContext('2d');

            context.font = "20px serif";

            const textAlign = [  "right" , "center" ,"left"  ];
            const textBaseline = ["top","middle","bottom"];

            textAlign.forEach( (e,i)=>{

                context.textAlign = e;

                textBaseline.forEach( ( e2,j) => {

                    context.textBaseline = e2;

                    const text = `文字枠(${e},${e2})` ;

                    const [ x , y ] = [ 110 * ( i + 1 ) + 100 , 50 * ( j + 1 )];

                    lineDraw( context , x - 200 , y , x + 200 , y);
                    lineDraw( context ,  x  , y + 50 , x  , y - 50);

                    context.beginPath();

                    const measure = context.measureText( text );

                    const pos =[
                        x - Math.abs(measure.actualBoundingBoxLeft),
                        y -  measure.actualBoundingBoxAscent,
                        measure.width,
                        measure.actualBoundingBoxAscent + measure.actualBoundingBoxDescent
                    ];
                    context.strokeStyle = "blue";

                    context.strokeRect( ...pos  );
                    context.fillStyle = "red";
                    context.fillText( text , x ,y);
                });
            });

        });
})();

キャンバス 文字枠 描画

更新日:2024/04/22

書いた人(管理人):けーちゃん

スポンサーリンク

記事の内容について

null

こんにちはけーちゃんです。
説明するのって難しいですね。

「なんか言ってることおかしくない?」
たぶん、こんなご意見あると思います。

裏付けを取りながら記事を作成していますが、僕の勘違いだったり、そもそも情報源の内容が間違えていたりで、正確でないことが多いと思います。
そんなときは、ご意見もらえたら嬉しいです。

掲載コードについては事前に動作確認をしていますが、貼り付け後に体裁を整えるなどをした結果動作しないものになっていることがあります。
生暖かい視線でスルーするか、ご指摘ください。

ご意見、ご指摘はこちら。
https://note.affi-sapo-sv.com/info.php

 

このサイトは、リンクフリーです。大歓迎です。