【JavaScript】canvasでアナログ時計
問題
canvasでアナログ時計って作れる?
答え
作りましょう。
今回は、1つのcanvas要素を用いて、1秒ごとに時計全体を書き直す形で実装する。
canvasは、ほぼWindows付属のペイントの表示領域のようなものと考えてよく、一度描画した図形を再取得して描画しなおしたり、位置をずらしたり、回転したりといったことはできない。フォトショップで言うレイヤーのようなものはなく、canvasが1つしかないなら、毎秒書き直すのがよくある実装だと思う。
時計の表示には以下の要素が考えられる、
- 文字盤
- 背景
- 時間の目盛り
- 分の目盛り
- 時針
- 分針
- 秒針
シンプルな時計を作るので、文字盤や背景は省略する。
時間の目盛り、分の目盛りはいつも固定位置に、時針、分針、秒針は時刻に応じた位置に表示する。
それぞれの描画メソッドをつくり、タイマーで1秒おきに更新できる仕組みを作ったら出来上がり。
Demo
Source
<canvas id="sample20130319" width="200" height="200"></canvas> <script> function clock(id){ this.id = id; this.init = function(){ this.timerId = null; this.canvas = document.getElementById(this.id); this.ctx = this.canvas.getContext('2d'); this.width = this.canvas.width; this.height = this.canvas.height; var x = this.ctx; x.translate(this.width / 2, this.height / 2); x.scale(this.width / 200, this.height / 200); x.rotate(-Math.PI/2); x.strokeStyle = "black"; x.fillStyle = "white"; x.lineCap = "butt"; } this.memoriM = function(){ var x = this.ctx; x.save(); x.lineWidth = 2; for (var i = 0; i < 60; i++) { x.beginPath(); x.rotate(Math.PI/30); x.moveTo(90,0); x.lineTo(100,0); x.stroke(); } x.restore(); } this.memoriH = function(){ var x = this.ctx; x.save(); x.lineWidth = 8; for (var i = 0; i < 12; i++) { x.beginPath(); x.rotate(Math.PI/6); x.moveTo(80,0); x.lineTo(100,0); x.stroke(); } x.restore(); } this.h = function(){ var x = this.ctx; x.save(); x.rotate(Math.PI/6 * (this.datetime.getHours() + this.datetime.getMinutes() / 60)); x.lineWidth = 8; x.beginPath(); x.moveTo(-5, 0); x.lineTo(60, 0); x.stroke(); x.restore(); } this.m = function(){ var x = this.ctx; x.save(); x.rotate(Math.PI/30 * (this.datetime.getMinutes() + this.datetime.getSeconds() / 60)); x.lineWidth = 4; x.beginPath(); x.moveTo(-5, 0); x.lineTo(80, 0); x.stroke(); x.restore(); } this.s = function(){ var x = this.ctx; x.save(); x.rotate(Math.PI/30 * this.datetime.getSeconds()); x.strokeStyle = "#cc0000"; x.lineWidth = 2; x.beginPath(); x.moveTo(-10, 0); x.lineTo(80, 0); x.stroke(); x.restore(); } this.ticktack = function(){ if (!this.canvas) { this.init(); } this.datetime = new Date(); var x = this.ctx; x.clearRect(-100, -100, 200, 200); this.memoriM(); this.memoriH(); this.h(); this.m(); this.s(); } this.start = function(){ if (!this.timerId) { var _clock = this; _clock.ticktack(); this.timerId = setInterval(function(){_clock.ticktack();}, 1000); } } this.stop = function() { if (this.timerId) { clearInterval(this.timerId); this.timerId = null; } } } //開始処理(jQueryがないときはwindow.onloadなどで) $(function(){ var x = new clock('sample20130319'); x.start(); }); </script>
メモ
- canvasの操作に関してはjQueryはあまり役に立たないので、開始の処理のところでしか使っていない。canvas操作のライブラリも使っていないので、ほぼ素のJavaScript。
- アナログ時計の場合、canvasのrotateを利用すると、円形に目盛りを並べたり、指定の角度で針を描画するのが簡単に書ける。
- 機能は現在時刻の表示のみとして作っているので、ボタンを押したら開始したいとか、指定の時刻を表示させたいといった場合は、もう一工夫必要。
- 拡大、縮小(scale)も利用すると、canvasの大きさに応じた表示が簡単にできる。
- 背景に画像を使うと、だいぶイメージの違うアナログ時計ができるでしょう。目盛りも背景に含めてしまうと、いちいちか描かなくてよくなって、プログラムもすっきりするでしょう。
コメント