miau's blog?

IE+ExplorerCanvas で Protovis を使ってみた

Protovis

MOONGIFT 経由で知った JavaScript のグラフ描画ライブラリ。Canvas タグを使用するそうで。

サンプルコードを見るとわかるけど、

:
.root.add(pv.Bar)
.data([1, 1.2, 1.7, 1.5, .7])
.height(function(d) d * 70).width(20)
.bottom(0).left(function() this.index * 25 + 4)
.anchor("bottom").add(pv.Label)
.root.render();

みたいな表記でデータ毎に必要な描画内容を定義する形なので、すごく柔軟なグラフが書ける。これは可視化大好きな人間としてはすごく魅力的。

ただ、素の IE は Canvas 非対応。HTA で PerlScript と連携させて使いたいような場合は、これだとちょっと困るわけで。IE 上で Canvas タグを動かす JavaScript ライブラリ ExtraCanvas を使って動かせるか簡単に試してみました。

簡単な機能しか試してないけど、結論としてはちょっとがんばれば動かせそう。




■事前準備

ExtraCanvas を落としておく。IE8 を使っているので、Release 3 を使う必要があるとこのこと。(参考: れぶろぐ - [Canvas] IE8 に対応した ExplorerCanvas Release 3 がリリース

とりあえず必要なのは excanvas.js だけだけど、DOCTYPE 宣言によっては ExtraCanvas が動かなかったりするそうなので(参考: IE8でもExplorerCanvasが利用できる)examples 配下の .html を改造して使うのがいいかも。

あと別途 Protovis(protovis.js)も落としておく。

で、コピーした .html、excanvas.js、protovis.js を同階層において、Dot の一番下のサンプルで試しました。

■とりあえず beautifier

protoviz.js は 1 行の JavaScript になってるのでエラーがわかりにくい。

メッセージ: オブジェクトでサポートされていないプロパティまたはメソッドです。
ライン: 1
文字: 2580

こんなこと言われても原因調べるの面倒だし。ということで、まずは Online javascript beautifier をかましておく。するとエラーは

メッセージ: オブジェクトでサポートされていないプロパティまたはメソッドです。
ライン: 171
文字: 1

こんな感じになるので、ある程度わかるように。

■イベント周りの対応

で、エラーの行を見てみると、

window.addEventListener(...

あー。IE だとイベント周り違うんだっけ?

この辺詳しくないんだけど、とりあえず

DOM Level 2 標準技術をMSIEで使う(イベント、基本操作) @ ぽかぽかWeb研究室

を ieevent.js として保存して、script タグであらかじめ読み込んでおくことに。

ちなみに上記の URL は fladdict.net blog: IEでaddEventListenerを使う メモ 経由。前者の方法ではうまくいかないケースもあるとのことなので、うまくいかない場合はこちらの方法を試したほうが?

■delete の対応

イベント周りは動くようになったけど、まだエラーが。

メッセージ: このオブジェクトではサポートされていない操作です。
ライン: 1634
文字: 9

該当の処理は・・・

delete this.scene[a].canvas.$clear

以下のサイトのコメント欄によると、window オブジェクト直下のものは delete 出来ない模様。このエラー行は canvas に対する処理みたいだけど、まあそういうものらしい。

風柳亭 - 別館:書庫のある庵 -: [JavaScript]GAE_xmlhttpRequest:クロスドメインのHTTP GET(Google App Engine経由)

とりあえず undefined を入れておけばいいようなので、

this.scene[a].canvas.$clear = undefined

みたいな感じに書き換え。他にも 1813 行目に canvas のメンバに delete している処理があったので、

this.scene[d].canvas.$offset = undefined

に念のため置き換え。

ちなみに

s/delete ([^\s;]+)/$1 = undefined/g

で全置換したりもしたけど、かえって不安定な動作になったりしたのでこの対策はよくないっぽい。

■JavaScript 1.8 の記述

サンプルコードは

.left(function() Math.random() * 100 + 25)

みたいな記述になってるけど、IE は JavaScript 1.8 に対応してないから、

メッセージ: '{' がありません。

みたいなエラーになってしまう。だから、

.left(function() { return Math.random() * 100 + 25 })

みたいに書き換える必要があるけど、面倒なので、

s/(function\(.*?\)) (.*)(\);?)/$1 { return $2 }$3/g

こんな感じで置換。function のあとにメソッドが続かなければ対応できるかと。

■動いたー

protovis

見てのとおり?mshta.exe でちゃんと動作してます。

■最終的なスクリプト

protovis_test.hta

<html>
<head>
<title>Protovis test</title>
<!--[if IE]><script type="text/javascript" src="excanvas.js"></script><![endif]-->
<!--[if IE]><script type="text/javascript" src="ieevent.js"></script><![endif]-->
<script type="text/javascript" src="protovis.js"></script>
<script type="text/javascript">
function load() {
var vis = new pv.Panel().canvas("cv");

vis.add(pv.Dot)
.data(["circle", "square", "triangle", "cross", "diamond"])
.left(function() { return Math.random() * 100 + 25 })
.bottom(function() { return this.index * 25 + 25 })
.shape(function(d) { return d })
.fillStyle(function() { return pv.Colors.category10.values[this.index] });

vis.render();
}
</script>
</head>
<body onload="load();">
<canvas id="cv" width="150" height="150"></canvas>
</body>
</html>


■注意点?

トップページのサンプルにある、

new pv.Panel().width(150).height(150)
:

という使い方も試したんですが、うまくいきませんでした。あとラベルの表示も行われなかった気がします。

がんばればできるのかもしれないけど、ひとまずこの件はクローズで。


(2009-04-21 追記)

Protovis 自体が JavaScript の Array オブジェクトを想定して作られているので、PerlScript と絡ませるのは難しいかも・・・。というか、PerlScript 側で JavaScript 側で Array として使えるデータを作る方法がわかりませんでした。
posted at 18:08:55 on 2009-04-03 by miau - Category: General No Trackbacks - Permalink

TrackBack

このエントリにトラックバックはありません
現在トラックバックは受け付けていません。

Comments

No comments yet

Add Comments

現在コメントは受け付けていません。
お手数ですが、 こちら のコメント欄にでも記載していただければと思います。