円弧(円の一部)または円を描くには,
コンテキスト.arc(中心のx座標, 中心のy座標, 半径, 開始角, 終了角, 回転方向);
の書式で書きます.
-図1-
図1にように,描画領域の左上端が(0,0)で,右に行くほどx座標(ピクセル単位)が増加します.他方で,初期設定では,y座標は下に行くほど増えることに注意してください.(数学の座標とは上下が逆です).
したがって,例えば x=50, y=60という点は,キャンバスの左上端から右に50ピクセル,下に60ピクセルだけ進んだところになります.
角と回転方向
(1) 単位はラジアンです.角度の単位:ラジアンは高校数学Ⅱで習いますが,分かりにくい場合に度の単位に直して使うには,次の関数を定義しておくと,度の単位で使える.
function d2r(degree1) //degree_to_radianを短縮したもの
{return degree1 * Math.PI / 180; //円周率πは,Math.PIにより求められる
}
よく使う角度について,ラジアンと度は次の図のように対応している.
-図2-
(2) 初期設定で,y座標が下に行くほど増えることと対応して,図2に示されるように,始線(0°[0ラジアン])を右向きにとって,円周上で始線から「時計回りに」進んだ角によって,開始角, 終了角の向き(場所)を決めます.次に,回転方向の引数は,反時計方向なら true[1でもよい],時計回りなら false[0でもよいが,-1などはダメ.0以外はすべて真=1と見なされる]で指定します.
- 図3 - - 図4 - - 図5 -
図3~図5は,ラジアンの単位で書いたもので,
図3は
コンテキスト.arc(50,50,40, 0, Math.PI, true);
と書いた場合で,x=50, y=50 を中心とする半径 r=40 の円周のうちで,開始角 0ラジアン,から,終了角πラジアンまで反時計回りに回ったときの半円になります.(線の色,幅は初期設定の黒,1ピクセルです)
図4は
コンテキスト.arc(150,50,40, 0, Math.PI, false);
と書いた場合で,x=150, y=50 を中心とする半径 r=40 の円周のうちで,開始角 0ラジアン,から,終了角πラジアンまで時計回りに回ったときの半円になります.(線の色,幅は初期設定)
図5は
コンテキスト.arc(250,50,40, 5*Math.PI/3, Math.PI/3, true);
と書いた場合で,x=250, y=50 を中心とする半径 r=40 の円周のうちで,開始角 5π/3ラジアン,から,終了角π/3ラジアンまで反時計回りに回ったときの円弧になります.(線の色,幅は初期設定)
この例のように,開始角 a,終了角 b で a>b のときは,開始角と終了角を入れ換えて,回転方向を逆向きにしたものと一致します.すなわち,図5は
コンテキスト.arc(250,50,40, Math.PI/3, 5*Math.PI/3, false);
と同じになります.
度の単位で書く
図6~図8は,度の単位で書くために,度からラジアンに変換する関数d2r(degree1)を定義して,開始角,終了角にそれを使っています.
- 図6 - - 図7 - - 図8 -
図6は
コンテキスト.arc(50,50,40, d2r(30), d2r(120), 1);
と書いた場合で,x=50, y=50 を中心とする半径 r=40 の円周のうちで,開始角 30°から,終了角120°まで反時計回り(1はtrue)に回ったときの円弧になります.2バイト文字の°のマークは書かない.(線の色は,コンテキスト.strokeStyle = "red";により赤,線の幅はコンテキスト.lineWidth = 10;により10ピクセル)
図7は
コンテキスト.arc(150,50,40,d2r(30), d2r(120), 0);
と書いた場合で,x=150, y=50 を中心とする半径 r=40 の円周のうちで,開始角 30°から,終了角120°まで時計回り(0はfalse)に回ったときの円弧になります.2バイト文字の°のマークは書かない.(線の色は,コンテキスト.strokeStyle = "blue";により青,線の幅はコンテキスト.lineWidth = 20;により20ピクセル)
図8は
コンテキスト.arc(250,50,20,d2r(30), d2r(120), -1);
と書いた場合で,x=250, y=50 を中心とする半径 r=20 の円周のうちで,開始角 30°から,終了角120°まで時計回り(-1はtrueなので,1の逆ではないことに注意)に回ったときの円弧になります.2バイト文字の°のマークは書かない.(線の色は,コンテキスト.strokeStyle = "green";により緑,線の幅はコンテキスト.lineWidth = 20;により20ピクセル).半径20ピクセルの円弧[参考としてやや白い色で示した線]に,幅20ピクセルの円周を描いても内部は埋まらないことに注意…幅20ピクセルの線は,半径20ピクセルの線を真ん中にして,その両側10ピクセルずつの線が引かれる
-図9-
数学座標では,コンピュータ上に初期設定で示される座標とは異なり,図9のようにy座標は上に行くほど大きくなります.このようにコンピュータ上の初期設定を変更して,x座標は変更せずにy座標だけ逆向きの座標系に変換するには,
コンテキスト.scale(1, -1);
とします.一般に,コンテキスト.scale(s, t);とすると,x方向にs倍,y方向にt倍して描画されます.
注意(1)この変換を行うと,円周上で角度を表す位置も上下が逆になり,次の図10のようになることに注意しましょう.
-図10-
注意(2)コンテキスト.scale(1, -1);によって,y座標の符号を逆にすると,次の図11,図12の元の座標のように画面上のy座標がすべて負になり,使いにくくなります.そこで,コンテキスト.translate(a, b);によって,原点を(a, b)に平行移動する変換を併用するとよい.
ただし,[1] コンテキスト.scale(1, -1);もコンテキスト.translate(a, b);もすでに描画されている図形には影響しない. [2] コンテキスト.scale(1, -1);とコンテキスト.translate(a, b);の記述順序が重要です.順序を変えると,異なる結果になります.
数学の教科書に出てくる,図13のような座標系にするには,コンテキスト.translate(50, 50);の後にコンテキスト.scale(50, -50);とすればよい.
- 図13 -
ただし,このようにスケールを拡大すると,デフォルトの線幅1では太すぎるので,コンテキスト.lineWidth = 0.01;などと半径の100分の1程度の線幅に変更する.
また,canvasのレファレンス・マニュアルに書かれている回転方向(anticlockwise)は,「反時計回り(true),時計回り(false)で分けるよりは」「x軸の正の向きからy軸の正の向きに(小さい方の角)90°で回る向きがfalse=0,(大きい方の角)270°で回る向きがtrue=1」と考えると,ブラウザでの実装と合う.
さらに,注意すべきこととして,コンテキスト取得後は,beginPath()の呼び出しの有無にかかわらず,コンテキスト.translate(a, b);やコンテキスト.scale(s, -t);を何度も使うと,座標系がさらに変換されることとなるので,複数の図形を同一キャンバス上に描く場合でも,コンテキスト.translate(a, b);やコンテキスト.scale(s, -t);は,初めに「1回」だけ使用することにすると,同一座標系での描画にできる.
- 図14 - - 図15 - - 図16 -
<canvas id="my_canvas3" width="300" height="100"></canvas>
<script type="text/javascript">
function deg2rad(degree1)
{return degree1 * Math.PI / 180;
}//度の角度をラジアンに変換する関数の定義
cname3 = document.getElementById("my_canvas3");
ctx3 = cname3.getContext("2d");
ctx3.translate(50,50);
ctx3.scale(50,-50);
//translate()とscale()は初めに1回だけ使う
ctx3.beginPath();
ctx3.arc(0,0,1,deg2rad(0), deg2rad(150),false);
//0°から150°まで左回り
ctx3.lineWidth = 0.01;
ctx3.stroke();
図14は
コンテキスト.arc(0,0,1,deg2rad(0), deg2rad(150),false);
により,0°から150°まで,x正→y正の近回り(=false)で円弧を描いたもの
(※反時計回りがtrueと覚えていると合わない)
ctx3.beginPath();
ctx3.arc(2,0,1,deg2rad(60),deg2rad(270),true);
//60°から270°まで右回り
ctx3.strokeStyle = "red";
ctx3.lineWidth = 0.02;
ctx3.stroke();
図15は
コンテキスト.arc(2,0,1,deg2rad(60),deg2rad(270),true);
により,60°から270°まで,x正→y正の遠回り(=true)で円弧を描いたもの
ctx3.beginPath();
ctx3.arc(4,0,1,deg2rad(270), deg2rad(60),false);
//270°から60°まで左回り
ctx3.strokeStyle = "green";
ctx3.lineWidth = 0.03;
ctx3.stroke();
</script>
図16は
コンテキスト.deg2rad(270), deg2rad(60),false);
により,270°から60°まで,x正→y正の近回り(=false)で円弧を描いたもの
図15と同じ形になる