前回 クリックするたびに文字を出現させる の続きです。前回は単純に文字を追加していっただけですが、今回はクリックした場所に文字を表示させる処理を解説します。
クリックされた場所に文字を描画する
今回はcanvas要素を使います。これはHTML5から新たに追加された要素です。これを使えばJavaScriptによって2Dや3Dの図形を描画することができるようになるのです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>クリックされた場所に文字を描画する</title> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel='stylesheet' href='./style.css' type='text/css' media='all' /> <style> </style> </head> <body> <p>クリックされた場所に文字を描画する</p> <canvas id = "can"></canvas> <script src='./app.js'></script> </body> </html> |
canvas要素で図形を表示できる幅と高さは、初期値で幅300px、高さ150pxです。ただしwidthとheight属性を指定すれば描画範囲を変更することができます。ただしCSSでcanvas要素のwidthとheightを指定してしまうとcanvas要素が拡大されるだけで描画範囲を変更することはできないので注意が必要です。
CSSでは描画範囲を変更ができないので境界線を描画するだけにとどめています。
style.css
1 2 3 |
#can { border: 1px solid #000; } |
問題のapp.jsですが、document.getElementById関数でcanvasを取得して、サイズを調整します。そのあとgetContext(‘2d’)を実行してコンテキストを取得します。fillText関数を呼び出せば文字の描画はできるのですが、問題はどこに描画するかです。
イベントリスナーの引数からクリックされた座標を知る
イベントリスナーの引数を使えばクリックされた座標をはじめとしてさまざまな情報を取得できます。ここでは最初にページ上におけるcanvasの座標を取得しています。ページ上でクリックされた座標はev.pageX、ev.pageYからわかります。両者を使えばcanvas上におけるクリックされた座標がわかります。
また文字を描画するときにクリックされた座標が中心になるようにしたいので、ctx.textAlign = ‘center’; ctx.textBaseline = ‘middle’;を指定しています。
app.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
let $canvas = document.getElementById('can'); $canvas.width = 320; $canvas.height = 400; let ctx = $canvas.getContext('2d'); ctx.font = '32px MS ゴシック'; document.onclick = (ev) => OnClick(ev); function OnClick(ev){ // canvas上におけるクリックされた座標を調べる let pos = GetCenterClicked(ev); // 取得された座標が中心になるように文字を描画する let text = '鳩'; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; ctx.fillText(text, pos.X, pos.Y); } function GetCenterClicked(ev){ // canvasの位置を取得 var canvasRect = $canvas.getBoundingClientRect() ; var canvasX = canvasRect.left + window.pageXOffset ; var canvasY = canvasRect.top + window.pageYOffset ; // クリックされたページ上の座標をcanvas上の座標に変換する let x = ev.pageX - canvasX; let y = ev.pageY - canvasY; return { X: ev.pageX - canvasX, Y: ev.pageY - canvasY, } } |
文字を矩形で囲む
あとで簡単なゲームをつくりたいので描画された文字を囲む矩形を描画します。そのためには文字の幅と高さを知る必要があります。文字の幅と高さがわかれば矩形の縦横の長さと矩形の左上の座標もわかります。
文字の縦横の長さを調べるにはmeasureText関数を使います。
1 2 3 |
let metrics = ctx.measureText(text); let textWidth = metrics.width; let textHeight = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent; |
これで文字の縦横の長さがわかります。文字の中心の座標はすでにわかっているので、ここから文字を囲む矩形の左上の座標を求めることができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
function OnClick(ev){ let pos = GetCenterClicked(ev); let text = '鳩'; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; ctx.fillText(text, pos.X, pos.Y); // 文字に枠をつける DrawRectangleAroundText(text, pos.X, pos.Y); } function DrawRectangleAroundText(text, centerX, centerY){ let metrics = ctx.measureText(text); let textWidth = metrics.width; let textHeight = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent; ctx.strokeRect(centerX-textWidth/2, centerY-textHeight/2, textWidth, textHeight); } |