uupaa-excanvas.js と ExplorerCanvas(excanvas.js) の違い

uupaa-excanvas.js 0.4α がダウンロード可能になりました。
最新版のダウンロード: http://code.google.com/p/uupaa-js-spinoff/downloads/list

uupaa-excanvas.js と ExplorerCanvas(excanvas.js) の違いについて書いてみます。
# uupaa-excanvas.js(ver 0.23), ExplorerCanvas(r3) について述べています。

同じ材料から同じ物を作ったら、味も同じなのか?

uupaa-excanvas.js と ExplorerCanvas は共に、IE がネイティブにサポートしていない HTML5::CanvasJavaScriptレベルで実装するものです。
Canvas API(I/F), 取り組むべき問題, 使える道具(VML + Silverlight), ゴールまでもが同じなので、ぱっと見は、両者はかなりそっくりになるはずです。

しかし、同じような材料(牛乳,卵,小麦粉,砂糖)で作ったケーキの味が、まったく同じになるはずがありませんよね?
今日は「見えない部分ではこんなにも実装が違ってるんだよ」風味な話をしようと思います。

使っている部品の違い

使っている部品の違いです。部品が違えば、それをドライブするロジックも異なります。

VML要素 DXImageTransform
uupaa-excanvas.js vml:shape, vml:stroke, vml:fill,
vml:oval,vml:textpath, office:spt, office:opacity2
Matrix, AlphaImageLoader
ExplorerCanvas vml:group, vml:image, vml:shape,
vml:stroke, vml:fill, office:opacity2
Matrix
  • ExplorerCanvas は 画像を vml:image で貼り付けますが、 uupaa-excanvas.js では AlphaImageLoader を使用しています。
    • 理由は、画像の拡大/縮小, マトリクス変形時に、vml:image を使用すると品質が劣化(ピンボケ)するためです。
  • 円形グラデーションをサポートする必要性から vml:oval を使用しています。
  • vml:textpath は テキストで使用します。
  • office:spt は ワードアートによるテキストの変形を回避するために使用しています。

サポートしている機能の違い

  • uupaa-excanvas.js
    • 未実装: MaxWidth, strokeText(in Silverlight)
    • 制限あり: createLinearGradient, createRadialGradient, clip, drawImage, globalCompositeOperation, shadowBlur, shadowColor, shadowOffsetX, shadowOffsetY
      • shadowは実装中です。次のバージョン(ver 0.3)で使えるようにする予定です。
      • createLinearGradient, createRadialGradient, clip はWebkit に対する完全互換ではありません。いくつかの制限が伴います。
  • ExplorerCanvas
    • 未実装: clip, createPattern, createRadialGradient, globalCompositeOperation, テキストAPI(strokeText, fillText, measureText, textAlign等), Shadow API(shadowBlur, shadowColor, shadowOffsetX, shadowOffsetY)
    • 制限あり: drawImage, fillStyle, strokeStyle, clearRect, drawImage + 移動/変形

どちらのライブラリにも実装されていない機能は以下になります。
toDataURL, getImageData, putImageData,
textBaseline, isPointInPath, arcTo

  • arcTo はHTML5::Canvasの仕様に不明瞭な点があり、実装を手控えている状態です。
  • textBaseline はフォントメトリクス(フォントの詳細な情報)にアクセスする手段がないため実装できません。
  • isPointInPath は高度に数学的なため実装できません。
  • toDataURL, getImageData, putImageData は VML / Silverlight で生のピクセルデータにアクセスする方法がないため実装できない状態です。
    • ActiveX経由(COM Object経由)なら以下のような方法もあります。
// 1. VC++ で、以下のような DLL(COM Object)を作成する。
STDMETHODIMP capture:: toBase64Png(x, y, w, h) {
    // Snapsie のコードを参考にしました
    CComPtr<IOleClientSite>     clientSite;
    CComPtr<IWebBrowser2>       browser;
    GetSite(IID_IUnknown, (void**)&clientSite);
    HRESULT hr = clientSite->QueryService(IID_IWebBrowserApp, IID_IWebBrowser2,
                                          (void **)&browser);
    HWND hwndBrowser;
    hr = browser->get_HWND((long*)&hwndBrowser);
    CComPtr<IDispatch> dispatch;
    hr = browser->get_Document(&dispatch);
    HDC hdc1 = ::GetDC(hwndBrowser);
    HDC hdc2 = CreateCompatibleDC(hdc1);
    CreateDIBSection();
    BitBlt();
    :
    :
}

// 2. regsvr32 capture.dll  を実行する

// 3. COM Object を ブラウザから使う
<script>
toDataURL: function(type) {
  var obj = new ActiveXObject("capture.capture"); // 矩形領域の画像をコピーするCOM Object
  var data = "";
  switch (type) {
  case "image/jpeg":
    data = "data:image/jpeg," + obj.toBase64Jpeg(x, y, w, h); // jpegなBase64データで受け取る
    break;
  case "image/png":
  default:
    data = "data:image/png," + obj.toBase64Png(x, y, w, h); // pngなBase64データで受け取る
    break;
  }
  return data;
}
</script>

この方法の欠点は、メリットがそれほど無いことと、regsvr32 が必要ということと、COM 関係のプログラミングには二度と関わりたくないという気持ちが強いことです。



http://uupaa-js-spinoff.googlecode.com/svn/trunk/uupaa-excanvas.js/DEMO.htm を見るとサポートしている機能の違いが、大体分かると思います。
# できれば SilverlightをインストールしたIEで見てください。

色のサポート

uupaa-excanvas.js は 様々な方法で色を指定できますが、ExplorerCanvas では注意が必要です。
ExplorerCanvas は rgb, rgba スタイルで色指定すると、描画の度に毎回文字列走査が入りますが、uupaa-excanvas.js は正規化した値(#ffffff, alpha値)をキャッシュし再利用します。

色の指定

uupaa-excanvas.js ExplorerCanvas
#fff
#ffffff
rgb(0,0,0)
rgb(0%,0%,0%) × (要素が描画されなくなる)
rgba(0,0,0)
rgba(0%,0%,0%) × (要素が描画されなくなる)
red (W3C named color)
pink (Web named color)
transparent × (alpha が 1 になり透過しない)

CanvasReady のサポート

Webページを表示し終わるタイミングと、Canvasが利用可能になるタイミングは別物です。
またこの条件はブラウザ毎に異なります。
uupaa-excanvas.js では uuCanvas.ready(), uuCanvas.Layer.ready(), uuCanvas.already() によりタイミングを知る方法を提供していますが、ExplorerCanvas には同様の機能がありません。

ブラウザ 描画可能なタイミング
IE DOM解析完了 + (該当する or 全ての) canvas 要素の初期化完了
Firefox DOM解析完了
Safari,Chrome DOM解析完了
Opera9.2 DOM解析完了
Opera9.5,10 Window.onload

動的に追加した canvas 要素の初期化

動的に canvas 要素を追加した場合は初期化が必要です。以下の方法で初期化を行います。

uupaa-excanvas.js

// 動的にcanvasを生成し初期化する
var elm = document.createElement("canvas");
document.body.appendChild(elm);
elm = uuCanvas.init(elm);
// 2Dコンテキストの取得
var ctx = elm.getContext("2d");

uuCanvas.Layer や uuCanvas.Draw を使うともっと簡単になります。

<script>
var layer, draw;

function canvasReady() {
  draw = new uuCanvas.Draw(layer.ref(1));
  draw.angleGlossy(0, 0, "GLOSSYBLOODORANGE", { r: 20, angle: 30 });
  layer.show();
}
window.onload = function() {
  layer = new uuCanvas.Layer(document.getElementById("layerSpace"), 300, 150);
  layer.addCanvas(300, 150).ready(canvasReady);
}
</script>
<div id="layerSpace" style="position: absolute; top: 0px; left: 0px;">


ExplorerCanvas

// 動的にcanvasを生成し初期化する(IE用に特別なコードを一行追加する)
var elm = document.createElement("canvas");
document.body.appendChild(elm);
if (document.uniqueID) { // for IE
  elm = G_vmlCanvasManager.initElement(elm); // IE用の初期化
}
// 2Dコンテキストの取得
var ctx = elm.getContext("2d");

VMLSilverlight の共存

ExplorerCanvas はバックエンドに Silverlight も使えるように開発が進んでいるらしいのですが、将来的に共存できる/できないかは不明です。

uupaa-excanvas.js は VMLSilverlight を同時に利用可能です。
Silverlight が使える環境なら自動的に Silverlightレンダリングしますが、以下のようにすることで VMLレンダリングを強制することが可能になり共存できます。

// 静的な canvas 要素に対しては、 class="vml" を指定する
<canvas class="vml" width="300" height="150"></canvas>

// 動的に生成する canvas 要素に対しては初期化時に VML の使用を強制できる。
<script>
var canvas = document.body.appendChild(document.createElement("canvas"));
canvas = uuCanvas.init(canvas, true); // 第二引数に真(trueや1)を指定すると、VMLでレンダリングされる
</script>

// uuCanvas.Layer 経由ならこうする。内部で uuCanvas.init(キャンバス, 1) が実行される。
var layer = new uuCanvas.Layer(document.body, 300, 150);
layer.addCanvas(300, 150, 1); // 第三引数に真(trueや1)を指定する

共存可能なことにより以下のメリットが生まれます

  • デバッグがとてもスムーズになる ⇒ SilverlightVMLレンダリングの違いを開発時に目視で比較できます。
  • ユーザの環境に左右されず、描画開始がスムーズに ⇒ ユーザの環境確認後に別々のスクリプトをロードする方法にくらべ、レンダリングをすばやく開始できます。
  • いいとこ取りができる ⇒ Silverlight には Silverlight のよさが、VML には VML のよさがあります。誤解している方もいらっしゃるようですが、現時点では Silverlight >>> VML ではないのです。VML モードでしか使えない機能(strokeText)もあります。
    • Silverlight のロードマップを見ると、いずれ VML の全ての機能をオーバーラップするようにも見えます。

ファイルサイズの違い

ソースコードを圧縮した状態とzipした状態のファイルサイズの比較です。

ソースコード 圧縮 圧縮 + zip
uupaa-excanvas.js 99.4kB 48.2kB 15.4kB
ExplorerCanvas 26.4kB 11kB 4.3kB

ExplorerCanvas の圧勝ですね。

実行速度の違い

http://uupaa-js-spinoff.googlecode.com/svn/trunk/uupaa-excanvas.js/DEMO.htm
uupaa-excanvas.js + Silverlight 環境下でのレンダリングVMLのそれに比べかなり高速です。

VMLレンダリング速度はほぼ互角です。uupaa-excanvas.js は ExplorerCanvas に比べ描画コストの高い機能(clip, グラデーション, globalCompositeOperation等)を実装していますが、速度的なペナルティはほとんど感じられないはずです。

ライセンスの違い

ExplorerCanvasApache License, Version 2.0 です。
uupaa-excanvas.js は MIT と Apache License, Version 2.0 のデュアルライセンスです。