html5 canvas 自動改行でテキストを描画するサンプルコード
2022-02-01 16:19:35
この記事では、キャンバス描画時のdrawTextの改行問題を解決する方法を紹介します。まず、キャンバスのテキスト描画で通常遭遇する問題を見てみましょう。
150×100のキャンバスで、境界がわかるようにボーダーがあります。
<canvas id="canvas" style="border:solid 1px darkgoldenrod;" width="200px" height="100px">& lt;/canvas>
まず、fillText()メソッドを見てみましょう。strokeText()メソッドも同様です。
var c=document.getElementById("canvas");
var ctx=c.getContext("2d");
ctx.fillStyle="#E992B9";
ctx.lineWidth=1;
var str = "If life cheats you, please don't be sad!
ctx.fillText(str,0,20);
固定幅のキャンバスで文字数が多い場合、fillText()は自動的に行を折り返さないことがおわかりいただけると思います。キャンバス自体の幅を広げることはできますが、これは問題の根本的な解決にはなりません。以前、canvasの基本的なAPIを紹介したときに、以下のような関数があったのを覚えていますか?
context.measureText(text)
この関数はフォントの幅と高さを測定するので、基本的にこの改行を処理するために、文字列の長さにおおよその幅を加えて計算するとよいでしょう。
その方法は次のとおりです。
var c=document.getElementById("canvas");
var ctx=c.getContext("2d");
ctx.fillStyle="#E992B9";
ctx.lineWidth=1;
var str = "If life cheats you, please don't be sad!
var lineWidth = 0;
var canvasWidth = c.width;//Calculate the width of the canvas
var initHeight=15;//draw the initial height of the font from the top of the canvas
var lastSubStrIndex= 0; //index of the string to start intercepting each time
for(let i=0;i<str.length;i++){
lineWidth+=ctx.measureText(str[i]).width;
if(lineWidth>canvasWidth){
ctx.fillText(str.substring(lastSubStrIndex,i),0,initHeight);//draw the intercepted part
initHeight+=20;//20 is the height of the font
lineWidth=0;
lastSubStrIndex=i;
}
if(i==str.length-1){//Draw the remaining part
ctx.fillText(str.substring(lastSubStrIndex,i+1),0,initHeight);
}
}
効果イメージはこちら
アルゴリズム 文字列strの各文字の幅とlineWidthを計算し、それがキャンバスの幅より大きい場合、この部分をインターセプトして描画し、lineWidthをリセットしてインターセプト開始の最後のインデックスを保存し、ループ変数iが最後の文字になったら、残りの部分を直接描画します。
次に、後で直接呼び出すのが簡単なメソッドにまとめます。
/*
str:the string to draw
canvas:canvas object
initX:the starting x coordinate of the string to draw
initY: the y coordinate of the start of the string
lineHeight: the height of the line, define a value yourself
*/
function canvasTextAutoLine(str,canvas,initX,initY,lineHeight){
var ctx = canvas.getContext("2d");
var lineWidth = 0;
var canvasWidth = c.width;
var lastSubStrIndex= 0;
for(let i=0;i<str.length;i++){
lineWidth+=ctx.measureText(str[i]).width;
if(lineWidth>canvasWidth-initX){/subtract initX,prevent the problem of border
ctx.fillText(str.substring(lastSubStrIndex,i),initX,initY);
initY+=lineHeight;
lineWidth=0;
lastSubStrIndex=i;
}
if(i==str.length-1){
ctx.fillText(str.substring(lastSubStrIndex,i+1),initX,initY);
}
}
}
以上、本記事の全内容をご紹介しましたが、皆様の学習のお役に立てれば幸いです。また、Script Houseをより一層応援していただければ幸いです。
関連
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン