読者です 読者をやめる 読者になる 読者になる

読み書きプログラミング

日常のプログラミングで気づいたことを綴っています

FlapjaxでHTML5 Canvas/SVGアニメーション

JavaScript

スマートフォンタブレットなど急成長中のプラットフォームでは、FlashSilverlightの代わりにHTML5 Canvasを使う流れが生まれています。でもまだCanvasは描画だけでアニメーション機能はありません。だからJavaScriptでアニメーションを作ることになります。
その時、きっとリアクティブプログラミングが主流になるんじゃないかなーと思って、Flapjaxを使ったアニメーションをやってみました。

Flapjaxとは

2006年から2009年にかけて開発されたリアクティブ(データフロー)プログラミング言語です。HTMLへの埋め込み型言語で、コンパイラはブラウザが実行可能なHTML+JavaScriptコードを生成します。
リアクティブプログラミングというのは、オブジェクト指向が絡み合った生物的なエコシステムの世界で、函数型プログラミングが時間の概念のない静寂な数理の世界、と例えると、どちらにもついていけない普通の人にとってのユートピアです。(冗談です)
リアクティブプログラミングは、引数が更新されると関数が再計算されるモデル上での言語です。よく表計算が例に挙げられます。(ハード設計者にはデータフローの名前で馴染み深いですね.非同期設計はなかなかしませんが。)
手続き型言語を使うと、ループを組んだり、ディペンデンシー定義したり、コールバック渡したりといったアルゴリズムにとって本質的でない部分に気を使うことになりますが、リアクティブプログラミングは言語仕様がその部分を吸収してくれます。

Flapjaxでcanvasアニメーション

http://www.flapjax-lang.org/try/のコード入力欄に以下のコードを入れて、Compile and Runしてみてください。

<html>
<head>
<title>Flapjax on Canvas</title>
<link rel="stylesheet" href="/demo.css"/>
</head>
<script type="text/javascript">
function drawarc(x, y) {
  var canvas = document.getElementById('draw');
  var ctx = canvas.getContext('2d');
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.beginPath();
  ctx.arc(x, y, 60, 0, Math.PI*2, false);
  ctx.stroke();
};
function drawrect(x, y) {
  var canvas = document.getElementById('draw');
  var ctx = canvas.getContext('2d');
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.beginPath();
  ctx.strokeRect(x, y, 30, 30);
};
</script>
<body>
<p>Flapjax on Canvas</p>
<canvas id="draw" width="400" height="400"></canvas>
<script type="text/flapjax">
var canvas = document.getElementById('draw');
drawarc(mouseLeftB(canvas), mouseTopB(canvas));
drawrect(Math.floor(timerB(30)*30/1000)%canvas.width, canvas.height/2);
</script>
</body>
</html>

右のフレームにコンパイル結果が表示されます。
Canvasの上を四角がゆっくり動きますが、マウスをCanvasの上で動かすと、マウスとともに円が動き回ります。
上記のコードには、四角を動かすようなsetIntervalや、
マウスに追従させて円を動かすようなmouseoverイベント記述が見当たらないことに注意してください。
timerB(30), mouseLeftB(c), mouseTopB(c)が更新された時、drawrect, drawarcを再計算するようなJavaScriptコードをFlapjaxが追加してくれています。


Flapjaxは、canvasだけでなく他のすべての要素をダイナミックにしてくれます。詳しくはFlapjaxサイトのデモをご参照ください。デモにはcanvasへの応用が見られなかったので、できるかどうか確かめてみたというのが本記事の主旨です。

結論は「できた」ですが、課題も見えました。

  1. Flapjaxを使うと、canvas上に非同期のアニメーションがどんどん追加できる。
  2. ところが、canvasの上で何かを「動かそう」とすると画面の消去が必要なため、追加するとき部品すべてを再描画する必要あり。
  3. それに伴い、画面のちらつきが多くなる。

仮想バッファなど、工夫、拡張が必要です。

JavaScript上のリアクティブプログラミングは、他にはRxJSが検索で見られましたが、アクティブかどうかよくわかりませんでした。これを制したものがMacromedia二世になる!?

SVG

(2011/07/10加筆)
SVGでもFlapjax機能しました。

<html>
<head>
<title>Flapjax Demo: Flapjax on SVG</title>
<link rel="stylesheet" href="/demo.css"/>
</head>

<body>
<svg id="svg">
<circle id="point" cx="100" cy="100" r="10" fill="red" />
<circle id="circle" cx="100" cy="100" r="50" fill="skyblue" />
</svg>
<script type="text/flapjax">
var svg = document.getElementById('svg');
var circle = document.getElementById('circle');
circle.setAttribute('r', Math.floor((timerB(30)%1000)/10));
var point = document.getElementById('point');
point.setAttribute('cx', mouseLeftB(svg));
point.setAttribute('cy', mouseTopB(svg));
</script>
</body>
</html>


<script>の内容は<svg>の外に記述する必要があるようです。