アナログ時計に時字を表示しよう
前回はアナログ時計に1分単位の目盛りを追加しました。
今回は前回のアナログ時計の盤面に、時字(ときじ)を表示してみましょう。
時字の表示のやり方
JavaScriptのcanvas上に文字を表示するには、fillText()かstrokeText()を使います。
この二つの違いは、テキストを塗りつぶすか輪郭として描画するかです。
fillText(文字列, X座標, Y座標 [, 最大幅]) | 指定したX座標、Y座標にテキストを塗りつぶして描画。 |
strokeText(文字列, X座標, Y座標 [, 最大幅]) | 指定したX座標、Y座標にテキストの輪郭を描画。 |
今回のアナログ時計を構成している円は背景を塗り潰しているので、fillText()で文字を表示しようとすると、円の背景色に塗り潰されて消えてしまいます。
そのため、今回は時字の描画には、strokeText()を使います。
また、文字を表示する時に指定する座標は、左下を基準にします。(下図の赤丸の位置)
文字を表示したい座標の中心(下図の赤丸の位置)に置きたいので、文字サイズの半分のサイズをX座標は左(マイナス)に、Y座標は下(プラス)にずらします。
今回は1文字を24ポイントにしているので、時字が1桁(1~9)の場合は12ポイント、2桁(10~12)の場合は24ポイントずらします。
アナログ時計に時字を表示するプログラム
アナログ時計に時字を表示するプログラムは、以下のようになります。
時字の表示位置は、あらかじめ配列として定義しておきます。
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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Clock</title> </head> <body onload="strClock();"> <canvas id="pos" width="400" height="400"></canvas> <script type="text/javascript"> // 定数 const CEN_X = 200; const CEN_Y = 200; const SEMICIRCLE = 180; // 針表示関数 function needle(fig) { // 現在時刻を取得 var now = new Date(); // 各針の角度を計算 var angle_h = Math.round(90 - 30 * now.getHours() - 0.5 * now.getMinutes()); // 短針 var angle_m = Math.round(90 - 6 * now.getMinutes()); // 長針 var angle_s = Math.round(90 - 6 * now.getSeconds()); // 秒針 // 円周側の座標を取得 var pos_hx = Math.cos(angle_h*(Math.PI/SEMICIRCLE))*120; var pos_hy = Math.sin(angle_h*(Math.PI/SEMICIRCLE))*120; var pos_mx = Math.cos(angle_m*(Math.PI/SEMICIRCLE))*160; var pos_my = Math.sin(angle_m*(Math.PI/SEMICIRCLE))*160; var pos_sx = Math.cos(angle_s*(Math.PI/SEMICIRCLE))*150; var pos_sy = Math.sin(angle_s*(Math.PI/SEMICIRCLE))*150; line(fig,pos_hx,pos_hy,12,"red"); line(fig,pos_mx,pos_my, 8,"green"); line(fig,pos_sx,pos_sy, 3,"blue"); } // 目盛り表示関数 function memory(fig) { for (angle=0; angle < 360; angle+=6) { // 正時 if (angle % 30 == 0) { fig.lineWidth = 5; var mark_i_x = Math.cos(angle*(Math.PI/SEMICIRCLE))*160; var mark_i_y = Math.sin(angle*(Math.PI/SEMICIRCLE))*160; } // 正時以外 else { fig.lineWidth = 2; var mark_i_x = Math.cos(angle*(Math.PI/SEMICIRCLE))*170; var mark_i_y = Math.sin(angle*(Math.PI/SEMICIRCLE))*170; } var mark_o_x = Math.cos(angle*(Math.PI/SEMICIRCLE))*180; var mark_o_y = Math.sin(angle*(Math.PI/SEMICIRCLE))*180; fig.beginPath(); // 新しいパスを作成 fig.moveTo(CEN_X+mark_i_x,CEN_Y-mark_i_y); // 線の開始座標 fig.lineTo(CEN_X+mark_o_x,CEN_Y-mark_o_y); // 線の終了座標 fig.stroke(); // 線を描画 } } // 直線表示関数 function line(fig,pos_x,pos_y,thick,color) { fig.beginPath(); // 新しいパスを作成 fig.lineWidth = thick; // 線の太さ fig.strokeStyle = color; // 線の色 fig.moveTo(CEN_X,CEN_Y); // 線の開始座標 fig.lineTo(CEN_X+pos_x,CEN_Y-pos_y); // 線の終了座標 fig.stroke(); // 線を描画 } // 時字表示関数 function number(fig) { fig.font = "24pt メイリオ"; arr = {300:1,330:2,0:3,30:4,60:5,90:6,120:7,150:8,180:9,210:10,240:11,270:12}; for (angle=0; angle < 360; angle+=30) { // 時字が10未満 if (arr[angle] < 10) { var mark_x = Math.cos(angle*(Math.PI/SEMICIRCLE))*140+200-12; // 時字が10以上 } else { var mark_x = Math.cos(angle*(Math.PI/SEMICIRCLE))*140+200-24; } var mark_y = Math.sin(angle*(Math.PI/SEMICIRCLE))*140+200+12; fig.strokeStyle = "darkorange"; // 時字の色 fig.lineWidth = 3; // 時字の太さ fig.strokeText(arr[angle], mark_x, mark_y); // 時字を描画 } } // 円表示関数 function circle(fig,mode,color,thick) { fig.beginPath(); // 新しいパスを作成 fig.arc(CEN_X,CEN_Y,180,0,Math.PI*2); // 円を描画 fig.closePath(); // パスの終了 // 塗りつぶし if (mode == "fill") { fig.fillStyle = color; // 塗りつぶす色 fig.fill(); // 輪郭描画 } else if (mode == "stroke") { fig.strokeStyle = color; // 線の色 fig.lineWidth = thick; // 線の太さ fig.stroke(); } } // 描画開始関数 function strDraw() { // ドキュメントオブジェクト作成 var id1 = document.getElementById('pos'); // 2Dオブジェクト作成 var fig = id1.getContext('2d'); // 画面初期化 fig.clearRect(0,0,400,400); // 円の輪郭描画 circle(fig,"stroke","gold",10); // 円の塗りつぶし circle(fig,"fill", "lightyellow"); // 目盛り描画 memory(fig); // 時字描画 number(fig); // 針描画 needle(fig); } // 開始関数 function strClock() { setInterval("strDraw();",100); } </script> </body> </html> |
ファイルをダブルクリックするとプログラムが実行され、WEBブラウザ上にアナログ時計が表示されます。
JavaScriptの詳しい使い方は、以下の「MDN Web Docs」を参照してください。