WebOS Goodies

WebOS の未来を模索する、ゲームプログラマあがりの Web 開発者のブログ。

WebOS Goodies へようこそ! WebOS はインターネットの未来形。あらゆる Web サイトが繋がり、共有し、協力して創り上げる、ひとつの巨大な情報システムです。そこでは、あらゆる情報がネットワーク上に蓄積され、我々はいつでも、どこからでも、多彩なデバイスを使ってそれらにアクセスできます。 WebOS Goodies は、さまざまな情報提供やツール開発を通して、そんな世界の実現に少しでも貢献するべく活動していきます。
Subscribe       

JavaScript で画像処理! canvas を使ってみよう

皆さん、canvas という新しい HTML 要素をご存知でしょうか。 Web ページ上でインタラクティブな画像生成を行う技術で、従来 Java や Flash などを使わなければできなかったようなビジュアル表現が、プラグインや特殊なツールなしで実現できます。もともとは Mac OS X の Dashboard 用に開発された技術なのですが、現在では Web Application 1.0 仕様に取り入れられ、Safari 以外にも Opera9 やFirefox1.5 が標準でサポートしています。残念ながら IE6 (および IE7)では表示できないのですが、その問題を解消する方法も見つかりました。そこで、本日はこの canvas 要素について簡単にご紹介しようかと思います。

概要

canvas を利用するには、まず canvas 要素でページ中に描画領域を用意し、JavaScript を実行して描画領域に図形を描画する、という手順を踏みます。まずはこれらの概要をご説明します。

canvas 要素

前述のとおり canvas 要素は Web ページ内に空の画像領域を確保します。感覚としては画像ファイルを指定しない img 要素のようなもので、Web ページ上での扱いもほぼ同じです。画像がないので src 属性がなく、代わりに width, height 属性で描画領域のサイズを明示しなければなりません。また、JavaScript で描画対象の canvas を特定するための id 要素を指定するのが普通です。例えば、150x150 ピクセルの描画領域を確保するには、以下のように記述します。

<canvas id="example_canvas" width="150" height="150"></canvas>

閉じタグを忘れると以降の内容が表示されなくなるので注意してください。詳細は後述しますが、canvas 要素内のテキストはブラウザが canvas をサポートしていないときの代替表示として使用されます。また、"<canvas/>" のような略記法は Firefox では通りますが Opera9 は許してくれないようです。上記のように記述するのが無難でしょう。

JavaScript

描画領域に実際に図形を描画するには、 JavaScript を利用します。 canvas をサポートしたブラウザでは canvas 要素のオブジェクトに getContext というメソッドが追加されていますので、それを呼び出して描画処理用のオブジェクト(描画コンテキスト)を取得します。具体的には以下のようなコードになります。

var canvas  = document.getElementByID("example_canvas");
var context = canvas.getContext("2d");

後は描画コンテキストに実装されたメソッドで canvas に表示内容を描画していきます。例えば、以下は 100x100 ピクセルの描画領域を確保してそこに赤い矩形を描画する HTML です。

<html>
 
<head>
<script type="text/javascript">
function page_onload()
{
  var canvas = document.getElementById("red_box");
  var ctx = canvas.getContext("2d");
  ctx.fillStyle = "rgb(255,0,0)";
  ctx.fillRect (10, 10, 80, 80);
}
</script>
</head>
 
<body onload="page_onload();">
  <canvas id="red_box" width="100" height="100"></canvas>
</body>
 
</html>

その描画結果は以下のようになります。

Canvas で描画した赤い矩形

ページロード時に canvas を描画する場合は、上記のように onload ハンドラに記述するのが無難です。 canvas をネイティブサポートしたブラウザならばグローバルスコープで描画メソッドを実行することも可能なようですが、後述する IE6 で表示する方法には適用できません。

さまざまな環境に配慮する

canvas をサポートしているブラウザは、現在のところ Mac OS X の Safari、 Firefox 1.5 以降(および同等の Gecko ベースブラウザ)、 Opera9 以降だけです(もし他にもあったらごめんなさい)。したがって、Web 上の公開ページで canvas 要素を使うときは、 canvas 非対応のブラウザに対してもある程度の配慮が必要です。以下、そのための方法をまとめました。

非対応ブラウザへの対応

canvas 非対応ブラウザに対応するためには 2 つのことを考える必要があります。まずは canvas 要素の代わりとして静的な画像などを表示させること、もうひとつは canvas 対応を前提にした JavaScript コードの実行を抑制することです。まずは代替内容の表示からみていきましょう。以下の HTML は、ブラウザが canvas をサポートしていれば canvas による描画内容を表示し、そうでなければ静的な画像である "subimage.jpg" を表示します。

<canvas width="100" height="100">
  <img src="subimage.jpg" />
</canvas>

HTML の仕様では理解できないタグは単純に無視するということになっていますので、 canvas 非対応ブラウザでは canvas タグは無視され、その中の img 要素が表示されます。これに対して、 canvas 対応ブラウザでは canvas 要素の内容は無視することになっているので、 img 要素は表示されず、 canvas だけが表示される、というわけです。ただし、 Safari だけはちょっと事情が異なりますので、 Safari への対応は後述します。

次は、 canvas 関連の JavaScript の実行を抑制する方法です。これは、 canvas 要素のオブジェクトに getContext メソッドが定義されているかどうかを調べることで実現できます。先ほどの赤い矩形を描画するコードこの処理を追加すると、以下のようになります。

var canvas = document.getElementById("redbox");
if(canvas.getContext)
{
  var ctx = canvas.getContext("2d");
  ctx.fillStyle = "rgb(255,0,0)";
  ctx.fillRect (10, 10, 80, 80);
}

これらの対応を施すことで、対応ブラウザでは canvas を駆使したインタラクティブな処理を行い、非対応ブラウザでも最低限の静的コンテンツを表示させることが可能です。少々面倒ですが、 Web で公開するページなら、最低限「そこになにが表示されるのか」はわかるようにするべきでしょう。

Safari への対応

上記の非対応ブラウザへの対応で、置いてきぼりをくってしまうのが Safari です。 Safaricanvas 実装は Web Application 1.0 仕様が検討される前に実装されたもので、もともと公開 Web ページで使われることは想定されていませんでした。そのため、 canvas 要素の内容を無視する機構が備わっていません。つまり、上記の対応を行ったページを表示すると、 canvas の画像と代替内容の両方が表示されてしまうのです。

これに対応する方法としては、 CSS を工夫するか、もしくは JavaScript で代替内容の表示を制御するという方法があるようです。前者が具体的にどのような方法を指しているのかは、残念ながら見つけることができませんでした。後者の一番簡単なやり方は、以下のように canvas がサポートされているときは代替内容の display スタイルを none に設定することです。

<canvas width="100" height="100">
  <span id="subimage"><img src="subimage.jpg" /></span>
</canvas>
 
<script type="text/javascript">
if(document.getElementById("redbox").getContext)
  document.getElementById("subimage").style.display = "none";
}
</script>

ただし、これに関してはどこまで対応するべきかは微妙かと思います。 Safari も将来のバージョンでは仕様に追従するでしょうし、代替内容が表示されてしまっても致命的ではない場合も多いかと思います。重要度と手間を天秤にかけて臨機応変に対応するのが良いでしょう。

Internet Explorer 6 への対応

さて、最後に大物、 Internet Explorer 6 への対応です。 Firefox の台頭でシェアを落としたとはいえ、IE6 はいまだに 9 割弱のシェアを維持しています。当 blog でのシェアは(内容が内容だけに^^;)だいぶ低いのですが、それでも 50% 弱を占める最大勢力です。ちなみに Firefox は 40% 強、 Opera は 10% 前後です。うんうん、頑張れ Opera

話がずれました。 IE6 は標準では canvas をまったくサポートしていませんが、上記のような事情から「IE では表示されません」では済まされない面があります。なんとかならないかと思っていたところ、やっぱり Google さんがやってくれていました。開発者向けサイトである Google CodeExplorerCanvas というプロジェクトにて、 IE6canvas を表示するための JavaScript コードが公開されています。このスクリプトをページに埋め込むだけで、不完全ながら IE6canvas の機能が使えるようになります。 閲覧者側でプラグインなどをインストールする必要はまったくありません。 Google さん素晴らしい!僕はもう一生あんたについていくよ(T∀T;

それでは、さっそく ExplorerCanvas を使ってみましょう。基本的には、必要なページにスクリプトを埋め込むだけです。手順は以下のようになります。

  1. ダウンロードページから最新版の .zip ファイルをダウンロードします。
  2. ダウンロードした .zip ファイルを展開します。
  3. 展開されたファイルの中の "excanvas.js" を Web から参照可能なディレクトリに配置します。
  4. canvas を使用したページのなるべく上のほう(可能なら <head> 要素の内部)に以下の記述を挿入します。"excanvas.js" の部分は正しい URL に変更してください。
<!--[if IE]>
<script type="text/javascript" src="excanvas.js"></script>
<![endif]-->

あとは先にご紹介したとおりに canvas を配置・描画するだけです。閲覧者の方々にはまったく手間をかけずに済むのがありがたいですね。ただし、さすがに完全互換とはいかないようで、現在私が把握している範囲で以下の制約があります。

  • ローカルファイルシステムにある HTML ファイルに埋め込むと、セキュリティー警告が出ます(これはどちらかというと JavaScript を実行することに対する警告ですが)。
  • グローバルスコープでは canvas のメソッドが実行できません。 onload やその他のハンドラ内で実行する必要があるようです。詳細は不明ですが DOM ツリーが完全に構築された後でないといけないのかもしれません。
  • ネイティブサポートのブラウザに比べて、描画速度はかなり落ちます。アニメーションなどは辛いかもしれません。
  • quadraticCurveTo メソッドの描画結果が正しくありません。おそらく初期の Firefox と同じバグだと思われます。対処方法は こちらのページをご覧ください。
  • arc メソッドの開始角を 0 、終了角を 2π で円を描画するときは、最後のパラメータ(回転方向)を false にしなければならない。
  • drawImage メソッドを使用するときは、 canvas 要素のスタイルに "position:relative;" もしくは "position:absolute" を指定する必要がある。でないと画像がページ左上に移動してしまう Σ(‾□‾;なんだそりゃ

その他にも非互換性を見つけたら、ここに追加していきますね。これらの制約はあるにせよ、これで公開 Web ページ上で胸を張って canvas を使うことができます。とくにレンタルの blog のような環境では、 Ajax を使ってサーバー側で画像処理するような技も使えませんので、その代わりとして重宝するのではないでしょうか。

本日は canvas 要素についてご紹介しましたが、いかがでしょうか。類似の技術である SVG などに比べて、 canvasJavaScript のメソッドとして実装されているため、従来の CG プログラミングのノウハウが応用しやすくなっています。さらに、 canvas を 3D に拡張した 3D Canvas の実装もかなり進んでいるようで、今後の発展にも目が離せません。本日はほんのさわりの部分しかご紹介できませんでしたが、今後の記事でさらなる詳細もご紹介するつもりですので、ご期待ください!(^^)

関連記事

この記事にコメントする

Recommendations
Books
「Closure Library」の入門書です。
詳しくはこちらの記事をどうぞ!
Categories
Recent Articles