Canvasでアニメーションを作る
●requestAnimationFrame() で短針、長針もあるアナログ時計
window.requestAnimationFrame() メソッドを使っています。
これは、アニメーションのために再描画させたい指定を呼び出すんだそうです。およそ毎秒60回の再描画をするらしい。
引数は1個だけで、描画させたい指定を書きます。
また、new Date() で時刻をゲットして、getSeconds() で秒、getMinutes() で分、getHours() で時を数値でゲットしています。その値を使ってそれぞれの時計の針を回転させています。
(秒針は先っぽのマルだけにしたけど)
この時計のアニメーションは、MDN(Mozilla Developer Network)Basic animations を参考にさせていただきました。
(ほぼコピペ。このページに合うようにソースを編集した後、時計のサイズやデザインを変えました。お世話になります。)
onload = function() {
window.requestAnimationFrame(clock);
};
function clock(){
var now = new Date();
var ctx = document.getElementById('canvas1').getContext('2d');
ctx.save();
ctx.clearRect(0,0,300,300); //毎回canvas全体をクリアしてから描画する
ctx.translate(150,150); //回転の起点をcanvasの中心にする
ctx.rotate(-Math.PI/2); //-90度回転で0時を起点に(デフォの起点は3時のところ)
ctx.strokeStyle = '#999';
ctx.fillStyle = '#000';
ctx.lineWidth = 3;
ctx.lineCap = 'round';
// 時計のフレームの描画
ctx.save();
ctx.beginPath();
ctx.arc(0,0,142,0,Math.PI*2,true);
ctx.stroke();
ctx.fill();
ctx.restore();
// 文字盤の「時間」マークを12個
ctx.save();
for (var i=0;i<12;i++){
ctx.beginPath();
ctx.rotate(Math.PI/6);
ctx.lineWidth = 9;
ctx.moveTo(123,0);
ctx.lineTo(124,0);
ctx.stroke();
}
ctx.restore();
// 文字盤の「分」マークを60個
ctx.save();
for (i=0;i<60;i++){
/*if (i%5!=0) {*/
ctx.beginPath();
ctx.rotate(Math.PI/30);
ctx.lineWidth = 5;
ctx.moveTo(123,0);
ctx.lineTo(124,0);
ctx.stroke();
/*}*/
}
ctx.restore();
var sec = now.getSeconds();
var min = now.getMinutes();
var hr = now.getHours();
hr = hr>=12 ? hr-12 : hr; //三項演算子(hrが12か12より大きけりゃ12引く。じゃなきゃそのまま)
// 長針の描画
ctx.save();
// 1時間に30度、1分には0.5度、1秒には「180/6時間分の秒数」度、じわ〜っと動くように
ctx.rotate( hr*(Math.PI/6) + (Math.PI/360)*min + (Math.PI/21600)*sec )
ctx.lineWidth = 10;
ctx.beginPath();
ctx.moveTo(0,0);
ctx.lineTo(80,0);
ctx.stroke();
ctx.restore();
// 短針の描画
ctx.save();
// 1分に6度、1秒には「180/30分の秒数」度、動くように
ctx.rotate( (Math.PI/30)*min + (Math.PI/1800)*sec )
ctx.lineWidth = 6;
ctx.beginPath();
ctx.moveTo(0,0);
ctx.lineTo(105,0);
ctx.stroke();
ctx.restore();
// 秒針の描画
ctx.save();
// 1秒に6度ずつ動くように
ctx.rotate(sec * Math.PI/30);
ctx.strokeStyle = '#0c0';
ctx.fillStyle = '#fff';
// 円の白塗り
ctx.beginPath();
ctx.arc(123,0,7,0,Math.PI*2,true);
ctx.fill();
// 外側の円
ctx.beginPath();
ctx.lineWidth = 2;
ctx.arc(123,0,7,0,Math.PI*2,true);
ctx.stroke();
// 内側の点
ctx.beginPath();
ctx.lineWidth = 5;
ctx.moveTo(123,0);
ctx.lineTo(124,0);
ctx.stroke();
ctx.restore();
ctx.restore();
window.requestAnimationFrame(clock);
}