javascriptでcanvasで三角関数で矢印線を書く
こんにちはSGKです。
ブラウザ上で Javascript を使って canvas 上に矢印線を書かなきゃいけない、そんなときがある。
それなら、ライブラリを使え、とググると出てくる。
いやしかし、いろいろあって自力で書きたいんです。
三角関数を使わないといけないっぽい。
プログラマーといってもWEBプログラマーなんて数学から遠いところにいる、、中高サボってきたツケが出たなと反省する。
「三角関数なんてどこで使うんだよ!」夕日に向かって叫んだあのころの自分に答えてやりたい、ココで使います。
さーどうしよう。どうしたか、をブログにまとめてみました。
まず。ブラウザ上で絵を描く場合 <canvas> という要素を使います。
この canvas に対して座標を指定して絵を書きます。
HTMLで <canvas width=”500″ height=”500″> と書くと 幅500、高さ500ピクセルの描画領域が用意されます。
横方向をx、縦方向をyで表し、左上がx:0, y:0、右下がx:500, y:500 となります。
この x, y の値を座標と言います。
例えば中央に水平の線を書く場合、始点 x:100, y:250 から 終点 x:400, y:250 に線を書く、のように指定します。
HTML+Javascript で書くと以下のようになります。
<html>
<body>
<canvas width="500" height="500"></canvas>
<script>
//どのcanvasに書くかを指定
var canvas = document.querySelector('canvas');
var ctx = canvas.getContext('2d');
//始点
ctx.moveTo( 100, 250 );
//終点
ctx.lineTo( 400, 250 );
//線の色
ctx.strokeStyle = 'black';
//線の太さ
ctx.lineWidth = 1;
//線を書く
ctx.stroke();
</script>
</body>
</html>
↓↓↓
さてこの線を矢印線にしようというのがこのブログの本題です。
まずは三角関数なんて使わずに考えてみる。
上記の ctx.stroke(); の下に以下を追加する。
※ちなみに線の色と太さは指定済みなので変える必要がなければ再度指定しなくて良い。
ctx.beginPath();
ctx.moveTo( 400, 250 );
ctx.lineTo( 390, 240 );
ctx.stroke();
ctx.beginPath();
ctx.moveTo( 400, 250 );
ctx.lineTo( 390, 260 );
ctx.stroke();
↓↓↓
を!書けたやん!何が数学じゃそんなもんいらんわ!
と思うのだがしかし、もし線が斜めだった場合どうなるんですかね、、
始点のy軸を以下のように変えると水平の線が斜めに傾きます。すると、、
//始点
ctx.moveTo( 100, 150 );
↓↓↓
やっぱり矢印がくずれました。
あ~もうこれ三角関数だ、三角関数を使わざるを得ない。サンキューオイラーアディオスチリチリ(意味不明)
矢印の書き方を文章化すると、
元の線の終点から元の線に対して45度傾いた同じ長さの短い線を両側に2本引けば矢印になる。
なのでまず元の線が何度傾いているかを Math.atan2 で調べます。
var rad = Math.atan2(yの終点 - yの始点, xの終点 - xの始点)
次に矢印の線を元の線に対して何度傾けるかをラジアンという単位の値から求めます。
var radA = 傾ける角度 * Math.PI / 180;
ラジアンは角度を円周率で表したもので、上記の式のように 180度 は 1π となるような値です。
三角関数と相性が良く、詳しくはやっぱり難しいのでwikiで。
実は Math.atan2 の返り値もラジアンで表した角度なので、Math.atan2 の返り値にこの値を足すと
矢印線の絶対的な角度を求めることが出来ます。
上記角度を Math.cos 、Math.sin に渡すと x座標・y座標の係数が出るので、これに矢印線の長さを掛けます。
この値は相対値なので、元線の終点から引くことで矢印線の終点の座標を求めることが出来ます。
矢印線1のxの終点 = xの終点 - 線の長さ * Math.cos( rad + radA );
矢印線1のyの終点 = yの終点 - 線の長さ * Math.sin( rad + radA );
で、上記は片側の矢印線の終点だけなので、もう一方の線を書くためには角度を引いたものを cos, sin に渡せば求めることが出来ます。
矢印線2のxの終点 = xの終点 - 線の長さ * Math.cos( rad - radA );
矢印線2のyの終点 = yの終点 - 線の長さ * Math.sin( rad - radA );
上記を踏まえて矢印線描画を関数化したのが以下のコード
<html><body>
<canvas width="500" height="500"></canvas>
<script>
//どのcanvasに書くかを指定
var canvas = document.querySelector('canvas');
var ctx = canvas.getContext('2d');
//矢印線書く関数( 描画するキャンバス, 始点x, 始点y, 終点x, 終点y, 矢印線角度, 矢印線長さ )
function aline(ctx, x1, y1, x2, y2, r, len){
//元の線
ctx.beginPath();
ctx.moveTo( x1, y1 );
ctx.lineTo( x2, y2 );
ctx.stroke();
//元の線の角度
var rad = Math.atan2(y2-y1, x2-x1);
//矢印線の角度
var radA = r * Math.PI / 180;
//矢印線1
ctx.beginPath();
ctx.moveTo( x2, y2 );
ctx.lineTo( x2 - len * Math.cos(rad+radA), y2 - len * Math.sin(rad+radA) );
ctx.stroke();
//矢印線2
ctx.beginPath();
ctx.moveTo( x2, y2 );
ctx.lineTo( x2 - len * Math.cos(rad-radA), y2 - len * Math.sin(rad-radA) );
ctx.stroke();
}
//線の太さ色を指定
ctx.strokeStyle = 'black';
ctx.lineWidth = 1;
//矢印線書く、角度は45度から20度に変えて鋭い矢印に
aline(ctx, 100, 100, 400, 300, 20, 14);
</script>
</body></html>
↓↓↓
ん~今まで矢印なんかエクセルとかでなんとなく書いてたけどこれも三角関数なんだな~。
ついでに、今回三角関数をひさしぶりに勉強し直して思い出したので言いたい、
「中高生ならびに小学生の皆、マイクラのエンドポータルの場所は三角関数でわかるよ!」
以上ブラウザ上で canvas、Javascript、三角関数を使って矢印線を書いてみた、でした。