2005-10-03

いい加減な canvas 要素の紹介

ポスト @ 23:07:37 , 修正 @ 2005-10-10 2:05:49 | canvas, mozilla

始めに

canvas 要素に関する情報は Drawing Graphics with Canvas がありますが、そこにはあまり詳しい解説は有りませんでした。そこで「もう少し詳しい解説を書いてみようじゃないか」と無謀にも思い、書きはじめました。ノロノロと少しずつ書いていきましたが、その間に Devmo に Canvas Tutorial の執筆が開始されました。Canvas Tutorial は非常に内容が充実しているのでこの記事も参考にしています。

また、この記事は自分が特に気になった機能をを中心に書いていますので非常に内容が偏っています。

canvas 要素とは

canvas 要素はカスタム描画を行うための要素です。

Apple が Mac OS X 10.4(Tiger) の Dashboard 実装のために開発し Dashboard 用に 2 次元グラフィックス機能が定義されました。Safari 1.3 に実装されました。その後 Apple、Mozilla、Opera などからなる WHATWG の Web Applicatoin 1.0 の一部分として標準化中にあります。

現在は 2 次元グラフィック機能が提供されていますが、WHATWG では今後 OpenGL ES の API を元にした 3次元グラフィックス用のコンテクストを策定する予定とのことです。

canvas 要素以外にも、Web 上の 2 次元グラフィックスといえば SVG 等がありますが canvas 要素の利点は何でしょうか ? 私は、描画した図形にアクセスすることはできないが、よりプログラミングしやすい設計になっているということではないかと思っています。 書いた後からの編集は必要ないが、図形を手っ取り早く描画したいというときに有効だと思われます。 例えば、四角形を 100 個描画したいという場合、SVG では rect 要素(ないしは path 要素)を DOM で生成して DOM ツリーに追加しなくてはなりません。しかし canvas ではメソッド一つで四角形を描画できます。 他にも、現在の描画を上書きしていくアニメーションを簡単に書くことができます。しかしそれほど他の仕様との住み分けを考えている訳では無いようです。

Mozilla の実装

Mozilla では WHATWG の仕様に基づいて 2 次元グラフィック用コンテクストを実装していますが、独自に拡張している部分もあります。公式に使われているバックエンドは cairo ですが、GDI+Java2D による実装もあるようです。

Mozilla の実装では canvas 要素には閉じタグ(</canvas>)が必須となっています。また canvas 要素は XHTML の名前空間(http://www.w3.org/1999/xhtml)に属しています。

基本

以降、2 次元グラフィックス機能について紹介していきます。 canvas 要素は widthheight という属性と toDataURLgetContext というメソッドを持っています。

widthheight はキャンバスの大きさを指定します。widthheight が変更されるとキャンバスに描かれた内容も初期化されます。

描画コンテクストを得るには getContext() を使います。2次元グラフィックの場合は getContext('2d') となります。

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');

その他ベンダによるコンテクストは getContext('ベンダ名-コンテクスト名') となるそうですが、今のところ無いようです。

未実装ブラウザ対策

canvas 要素が実装されていないブラウザでは canvas 要素は表示されないので代替内容を書いておきましょう。object 要素等と同じように <canvas> と </canvas> の間に代替内容を書きます。

<canvas>代替内容</canvas>

また JavaScript でエラーを起こさないようにするために Canvas Tutorial では

var canvas = document.getElementById('canvas');
if (canvas.getContext){
  var ctx = canvas.getContext('2d');
  // drawing code here
}

というのが紹介されています。また

var canvas = document.getElementById('canvas');
if (!canvas.getContext) return;

の方が良いかもしれません。因みに私は以下のようなコードを使っていました。

try {
  var ctx = document.getElementById('canvas').getContext('2d');
} catch (ex) {}
if(!ctx) return;

画像をデータ URI に変換する

  • toDataURL()

初期値は image/png ですが、WHATWG の仕様には image/jpeg、image/svg+xml などもあがっています。現在 Mozilla では image/png のみをサポートしており、image/jpeg などが指定されても image/png の結果を出力します(WHATWG の仕様どおり)。Gecko が cairo に移行されと、application/pdf にも対応するかもしれません。

canvas.toDataURL();
canvas.toDataURL('image/png');

toDataURLAs() という Mozilla の独自拡張のメソッドがありますが、現在は toDataURL と変わらないようです。

パス

この章は非常にやる気がありません。

  • beginPath()
    • パスを開始する。これを指定しないとパスとして認識されません。
  • closePath()
    • パスを閉じる。始点と終点が直線で結ばれます。
  • moveTo(x 座標, y 座標)
    • 座標を移動します。図形は描画されません。
  • lineTo(x 座標, y 座標)
    • 直線を描きます。
  • quadraticCurveTo(制御点の x 座標, 制御点の y 座標, 終点の x 座標, 終点の y 座標)
    • 二次曲線を描きます。
  • bezierCurveTo(制御点1の x 座標, 制御点1の x 座標, 制御点2の x 座標, 制御点2の x 座標, 終点の x 座標, 終点の y 座標);
    • ベジェ曲線を描きます。これらの曲線は人が手で書くのは難しいです。
  • arcTo(始点の x 座標, 始点の y 座標, 終点の x 座標, 終点の y 座標, 半径)
    • 円弧を描きます
  • arc(x 座標, y 座標, 半径, 開始角度, 終了角度, 左回り(時計と逆向き)かどうか?)
    • 円弧を描きます。arc の角度指定は両方とも ラジアン です。左回り(時計と逆向き)かどうか?は true か false の値を取ります
  • rect(x 座標, y 座標, 幅, 高さ)
    • 矩形を描きます。

以下のメソッドを実行しないと実際に描画は行われません。

  • fill()
    • 塗りつぶし
  • stroke()
    • 線を描画
  • clip()
    • 切りぬき

四角形

  • fillRect(始点の x 座標, 始点の y 座標, 幅, 高さ)
  • strokeRect(始点の x 座標, 始点の y 座標, 幅, 高さ)
  • clearRect(始点の x 座標, 始点の y 座標, 幅, 高さ)

四角形の指定方法は (始点の x 座標, 始点の y 座標, 幅, 高さ)の順に指定します。

fillRect() は指定された範囲を塗りつぶしの四角形で描画します。

strokeRect() は指定された範囲を枠の四角形で描画します。

clearRect() は指定された範囲を消します(透明の黒で塗りつぶします)

色等

  • strokeStyle
  • fillStyle

strokeStyle は枠のスタイルを、fillStyle は塗りつぶしのスタイルを決定します。後述するグラデーションやパターンを使わない場合は色を指定します。

色の記述方法は何通りかあります。CSS 3 Color の記述方法が使えます。標準では黒です。

  • 色名
  • transparent
  • currentColor
  • #rgb
  • #rrggbb
  • rgb(赤, 緑, 青)
  • rgba(赤, 緑, 青, 透明度)
  • hsl(色相, 彩度, 明度)
  • hsla(色相, 彩度, 明度, 透明度)

色名は HTML 4 で定義されているものだけではなく SVG 1.0 で定義された色も指定できます。 transparent は透明で、 rgba(0,0,0,0) を意味します。clearRect() などで使われる透明の黒はこれを意味しています。 currentColor は現在使われている色を表します。rgb()、rgba() では赤、青、緑の指定に % と 0 から 255 までの数値による指定ができます。rgba()、hsla() とも透明度は 0 から 1 までの数値です。

線のスタイル

  • lineWidth = 数値
  • lineCap = butt/round/square
  • lineJoin = miter/round/bevel

線の太さは lineWidth で指定します。初期値は 1.0 です。

線の端は lineCap で指定します。 butt、round と square の値を取れます。butt は初期値で端を作りません、round は線の幅の 1/2 の長さの半円の端を作ります。square は線の幅の 1/2 同じ長さの四角い端を作ります。

線と線の接続方法 lineJoin は miter は round と bevel の値を取ります。初期値は miter で直線的に接続します。 round は角で常に幅が一定になるように丸めます。bevel は角が削られたような形になります。

サンプルが Canvas tutorial にありますので、そちらを御覧ください

画像の表示

  • drawImage(img/canvas 要素, 表示される x 座標, 表示される y 座標)
  • drawImage(img/canvas 要素, 表示される x 座標, 表示される y 座標, 表示される幅, 表示される高さ)
  • drawImage(img/canvas 要素, 切り抜き始める x 座標, 切り抜き始める y 座標, 切り抜く幅, 切り抜く高さ, 表示される x 座標, 表示される y 座標, 表示される幅, 表示される高さ)

HTML の img 要素や canvas 要素の中身を描画できます。img 要素は new Image() で生成したり、 document.images 等でアクセスできます。もちろん document.getElementById 等でも取得したノードを指定することができます。

引数の数によって処理方法があるので注意が必要です。引数が足りないとエラーが発生します。引数3個の場合は画像を指定された座標に表示する、引数5個の場合は画像を拡大縮小して表示する。引数9個の場合は切り抜いて表示します。

変形

  • translate(移動先の x 座標, 移動先の y 座標)
  • scale(倍率)
  • rotate(回転角)

translate() は移動を行います。translate() した先が新しく (0,0)になります。scale() は拡大縮小を行います。引数倍されます。rotate() は回転を行います。引数はラジアンでは無くです 引数はラジアンです

グラデーション

  • createLinearGradient(始点の x 座標, 始点の y 座標, 終点の x 座標, 終点の y 座標)
  • createRadialGradient(1始点の x 座標, 始点の y 座標, 始点の半径, 終点の x 座標, 終点の y 座標, 終点の半径)
  • グラデーション.addColorStop(ストップの位置, 色)

fillStylestorkeStyle にグラデーションを設定することでグラデーションを持った図形を描画できます。 線形グラデーションと円形グラデーションがサポートされています。 createLinearGradient() は線形グラデーション、createRadicalGradient() は円形グラデーションを作ります。 グラデーションストップはグラデーションに addColorStop() を使って指定します。第1引数が場所です。場所は 0 がグラデーションの始点で 1 がグラデーションの終点です。

ctx.fillStyle = ctx.createLinearGradient(0, 0, 0, 100);
ctx.fillStyle.addColorStop(0, 'yellow');
ctx.fillStyle.addColorStop(1, 'green');

また

var radialG = ctx.createRadialGradient(155, 155, 50, 155, 155, 25);
radialG.addColorStop(0, 'navy');
radialG.addColorStop(0.75, 'aqua');
radialG.addColorStop(1, 'blue');
ctx.strokeStyle = radialG;

等と変数としておく方法が Canvas Tutorial にあります。こちらの方がよいでしょう。

パターン

  • createPattern(img/canvas要素, 繰り返しパターン)

WHATWG の仕様ではパターンの実装はオプションですが、Mozilla では実装してます。 fillStylestrokeStyle にパターンを設定することでパターンを持った図形を描画できます。 第1引数がパターンとなる img/canvas 要素、第2引数が繰り返し方法です。 繰り返し方法は repeat と repeat-x repeat-y no-repeat です。それぞれの値の意味は CSS の background-repat と同じですといえば分かり易いでしょうか。repeat は縦と横に繰り返し、repeat-x は横に繰り返し、repeat-y は縦に繰り返し、no-repeat は 繰り返し無しです。

var pttr = new Image();
pttr.src = 'pattern.png';
ctx.fillStyle = ctx.createPattern(pttr, 'no-repeat');
ctx.strokeStyle = ctx.createPattern(pttr, 'repeat');

パターンを未実装の場合は createPattern() は null を返します。

  • shadowColor = 色
  • shadowOffsetX = 数値
  • shadowOffsetY = 数値
  • shadowBlur = 数値

影のサポートもオプショナルです。Mozilla では現在の所実装していません。 shadowColor で影の色を shadowOffsetXshadowOffsetYで影がどれだけ離れるかを設定します。 shadowBlur では影のぼかし具合を指定します。 shadowColor は透明の黒、shadowOffsetXshadowOffsetY は 0、shadowBlur も 0 で初期化されます。

コンポジション

  • globalAlpha = 数値
  • globalCompositeOperation = 方法

globalAlpha は全体の透明度を指定します。0(透明)から 1(不透明)までの値を取り、初期値は 1.0 です。

ctx.globalAlpha = 0.5;

globalCompositeOperation は描画されるグラフィックスの処理方法を指定します。

  • destination-atop
  • destination-in
  • destination-out
  • destination-over
  • source-atop
  • source-in
  • source-out
  • source-over
    • 標準です。
  • xor
  • over
  • copy
  • darker
  • lighter
    • Mozilla の実装ではバグがあるそうです。
  • clear
    • これは Mozilla の独自実装です

詳しいことは仕様書を読むか、実験して下さい(いい加減極まりない)。

ウィンドウのキャプチャ

  • drawWindow(window, 始点の x 座標, 始点の y 座標, 幅, 高さ, 背景色)

これは Mozilla が独自に実装した機能でウィンドウのキャプチャを行います。このメソッドを使うには chrome 特権が必要です。

ctx.drawWindow(window, 0, 0, 100, 200, "rgb(0,0,0)");

背景色で塗りつぶされた領域にキャプチャされた結果が書き込まれるようです。'rgba(0,0,0,0)' が背景色に指定されると透明な領域にキャプチャした内容を描画するようです。WMODE="transparent" の Flash 以外のプラグインのキャプチャはできないそうです。

更新記録

10/10 rotate の引数がラジアンだったので度と誤っていた書いていたのを修正。

10/04 改題