この記事は「HTMLでトーナメントの作成」をテーマに、連載のような形でいくつかの記事で一つになるようにしています。
まとめページとして以下の記事をご参照ください。
リンク:トーナメントの作成まとめ記事
Canvasでやりたいこと
まずはCanvasに何をしてもらいたいかを整理します。
Canvas is 何?
そもそもCanvasとは何か?
詳しいことは詳しく書いている記事に任せて、雑に言えば「JavaScriptでHTMLに絵が描ける」機能です。
それを使って、トーナメントの線を引いたり、勝敗結果の赤線を引いたりします。
できないといけないこと
では
「トーナメントの線を引く」
「勝敗結果を赤線で更新する」
を実現するために、実際に何ができないといけないか?
私は次の3つと考えました。
- 座標指定で線を引く
- 別の色で上書きする(「塗り替える」でなくていい)
- Canvasタグ内にHTML要素を重ねる
1,2は当たり前というか絵が描けるなら当然できるでしょうが、問題は3つ目です。
トーナメントを簡単に更新するためにテキストボックスやセレクトボックスを使うつもりですが、それを同じ範囲内でやらないといけません。
入力範囲と表示範囲を別にしてしまえばいいですが、それでは直感的ではなくややこしいです。
解決策を探したところ、幸い同じようなことを考えた先人がいたようで、参考になるページがありました。
これで実現可能だとイメージできたので、実際に試していきます。
Canvasを使ってみる
直線を引く
まずは基本中の基本、線を引いてみます。
main.htmlのファイルに以下を書き加えます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8" />
<title></title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="./style.css">
<script src="./tournamentJs.js"></script>
<script>
onload = function() {
var canvas = document.getElementById('sample');
var cvs = canvas.getContext('2d');
cvs.beginPath();
cvs.moveTo(0, 50);
cvs.lineTo(200, 50);
cvs.moveTo(100, 0);
cvs.lineTo(100, 300);
cvs.stroke();
};
</script>
</head>
<body>
<canvas id="sample" width="500" height="500">
</canvas>
</body>
</html>
main.htmlを開くと、十字架のような線が引けていると思います。
簡単に解説します。
canvasを使うためには、まずcanvasタグを用意します。
絵を描くには紙を用意しないといけない、そんなイメージです。
<body>
<canvas id="sample" width="500" height="500">
</canvas>
</body>
これで500×500の白紙が用意されます。
描画はjavascriptで行います。
onload = function() {
var canvas = document.getElementById('sample');
var cvs = canvas.getContext('2d');
};
onloadでページを開いたときに処理するように宣言します。
変数canvas
にはhtmlに書いたcanvasタグをgetElementById
で持ってきています。
次に変数cvs
にcanvasのコンテキストを入れて編集する準備を整えます。イメージしにくい場合、ここではいったん「画材を机に並べる」操作と思って下さい。
これで実際に線を引く準備ができました。
線を引く処理を書いていきます。
cvs.beginPath();
cvs.moveTo(0, 50);
cvs.lineTo(200, 50);
cvs.moveTo(100, 0);
cvs.lineTo(100, 300);
cvs.stroke();
各命令の意味と、手で書く場合でのイメージを書いてみます。
beginPath
:直線を引く準備(定規を手に持つ)
moveTo
:ポインタを動かす
(ペン先を浮かせて、ペンを動かす)
lineTo
:現在のポインタを始点に、指定の点まで直線を引く
(ペン先を紙につけて、ペンを動かす)
stroke
:引いた線を実体化する(ペン入れ)
赤線で上書き
ではこの十字架の縦線を、少し太めの赤で上書きしてみます。
cvs.lineWidth = 3;
cvs.strokeStyle = "red"
cvs.beginPath();
cvs.moveTo(100, 0);
cvs.lineTo(100, 300);
cvs.stroke();
新しい処理が出ました、こんなことをしています。
lineWidth
:線の太さを変更(ペンを持ち替える)
strokeStyle
:線の色を変更(インクの変更)
これにより、main.htmlを開くと次のような図が出ると思います。
また、beginPath
が再び登場しているのはなぜかというと、「別の作業を始めるぞ」という宣言のようなものです。
1回目のbeginPath
を消すと、「さっきの横線も同じペンを使うんだな」と判断され、縦も横も赤い線になってしまいます。
HTML要素を重ねる
さて、最後にこの線の上にテキストボックスを表示してみます。
作業する前にhtmlのpositionについて下記ページを確認。
目的としては指定した位置に強制的に表示したいので、絶対位置での表示のabsolute
を使いたいです。
このとき、基準点をcanvasの表示範囲にしたいので、親のタグをrelative
で指定したいです。
雑に言うとこういう感じです。
relative
:これを付けたものを基準点に、これを付けたタグの子の要素の位置に影響する。
absolute
:これを付けた要素の位置を指定位置にする。指定の基準点は親の要素。
よくわからない?私も混乱してきました。まぁ雰囲気でやってください。コーディングはふいんき。
canvas
の上に親要素を追加しないといけないので、div
で囲います。数字は適当です。
<body>
<div style="position:relative">
<canvas id="sample" width="500" height="500">
</canvas>
<input type="text"
style="position:absolute; left:30px; top:40px">
</div>
</body>
表示してみると、線の上にテキストボックスができていると思います。
これで具体的に何がしたいかを改めて確認します。
テキストボックスとセレクトボックスでトーナメントの名前表示・編集を行い、canvasで線を引いて表を作ります。
絵にするとこんな感じ。
黒線と赤線をcanvasで表現、変なスペースができないようにちょっと長めに線を引いて、テキストボックスとセレクトボックスを重なるように配置していきます。
大丈夫?ちゃんとできる?
できらぁ!
ひとまず今回はここまでです。
これで技術的な課題は解決できたと思っています。
あとは処理を作り上げるだけかなと思います。
次回はテキストボックスとセレクトボックスを、
入力に合わせて自動配置する処理を作ります。
まとめリンク:トーナメントの作成まとめ記事
引用