Monthly Archives: 3月 2009

2009-03-19

JavaScriptでタイマーイベントとcanvas要素を使う

一枚絵を描くだけじゃつまらない、と言われればなるほどごもっとも。やはり動きが見えてこそ、プログラムの甲斐があるという物でしょう。時間に沿った変化。それを実現する鍵になるのがタイマーです。

タイマーを使うには次の関数を使います。

  • setTimeout(f, t)
  • setInterval(f, t)

setTimeoutはtミリ秒経過後に一回だけ関数fを呼び出すよう、タイマーをセットします。

setIntervalはtミリ秒間隔で関数fを繰り返し呼び出すよう、タイマーをセットします。

まずはsetTimeoutから。

function f1()
{
  alert("f1呼ばれた");
}

setTimeout(f1, 1000);

1000ミリ秒後にメッセージを出します。実行は例によってインタラクティブコンソールで可能。

JavaScriptはコード中で自由に関数を作れるので、次のように書いても……

var f2 = function(){ alert("f2呼ばれた");}
setTimeout(f2, 1000);

次のように書いても……

setTimeout(function(){alert("f anonymous呼ばれた");}, 1000);

同じです。

これを使って絵を描いてみましょう。

var cv = document.createElement("canvas");
cv.setAttribute("width", "320");
cv.setAttribute("height", "240");
cv.style.cssText = "border: 1px solid;";
document.body.appendChild(cv);
var ctx = cv.getContext("2d");

setTimeout(drawLine, 50); //50ms後以降にdrawLineを呼び出すようセットする。

function drawLine()
{
  ctx.strokeStyle = "#" + Math.round(Math.random() * 0xffffff).toString(16); //色をランダムで決める。
  ctx.beginPath();
  ctx.moveTo(Math.random() * 320, Math.random() * 240); //始点をランダムで決める。
  ctx.lineTo(Math.random() * 320, Math.random() * 240); //終点をランダムで決める。
  ctx.stroke();
  setTimeout(drawLine, 50); //再度タイマーをセットする。
}

線が増えていく様子が確認できると思います。

setTimeoutは一回きりの呼び出しに使いますが、こうして呼び出されたときに再度タイマーを設定すれば、繰り返し呼び出すような用途にも使えます。

次はsetInterval。setIntervalは止めるまでずっと一定の間隔で関数を呼び出し続けようとします。

var cv = document.createElement("canvas");
cv.setAttribute("width", 120);
cv.setAttribute("height", 120);
cv.style.cssText = "border: 1px solid;";
document.body.appendChild(cv);
var ctx = cv.getContext("2d");

var second = 0;

setInterval(
  function(){
    // 秒をカウント。スコープの外のsecondを参照していることに注意。
    ++second;

    // キャンバスを透明色で塗りつぶす。
    ctx.clearRect(0, 0, 120, 120);

    // 円を描く。
    ctx.strokeStyle="#000";
    ctx.fillStyle="#fff";
    ctx.lineWidth = 4;
    ctx.beginPath();
    ctx.arc(60, 60, 50, 0, Math.PI*2, false);
    ctx.fill();
    ctx.stroke();

    // 秒針を描く。
    ctx.strokeStyle="#f00";
    ctx.beginPath();
    ctx.moveTo(60, 60);
    ctx.lineTo(
      60+Math.sin(Math.PI * second / 30)*40,
      60-Math.cos(Math.PI * second / 30)*40);
    ctx.stroke();
  }
  , 1000);

setTimeoutで繰り返すと少しずつ実際の経過秒数とずれていってしまうのですが、setIntervalなら大丈夫です。

2009-03-19

眼鏡

個人的には普段考えたこともない意外な感じ。私、眼鏡を引け目に思ったなんてことは、今まで一度もない。私が眼鏡をかけ始めたのは小学校4~5年の頃だったと思うけど、それで人にからかわれたとかそういうことは全くなかった。すんなり周囲に受け入れられたと思う。友達にも眼鏡をかけている人はいたし、どちらかと言えばポジティブな印象を持っている。もちろん幼い頃からかけている人の中には、嫌な思いをした人もいるだろうが。運動能力? ナンセンス! 眼鏡をかけていても人並み以上に運動できたよ。それと、私にはコンタクトレンズを使いたいという人の気持ちが全く理解できない。目に異物を入れて何が楽しいんだろう。コンタクトレンズと悪戦苦闘していた姉を見ていると、コンタクトレンズがそれほど良いものとは思えない。使わなければならない状況になってしまった人は本当に気の毒だと思う。

と、そんなことはどうでも良いのだが、「メガネを外すと美少女」の逆がもっと欲しいという話を見て思ったこと。

  • 昔NHKのドイツ語講座で長岡ナターシャという講師が居てだな……。
  • めがねっこ、めがねっこ、がねっこ。忘却の旋律?