CanvasによるJavaScriptグラフィック

導入

描画領域の作成

グラフィックを描画する領域はcanvas要素で作成します。描画処理は、その要素から取得できるCanvasRenderingContext2Dオブジェクトを介して行います。

<canvas id="image-box" width="100" height="100"></canvas>

<script type="text/javascript">

  var canvas = document.getElementById( 'image-box' );
  if( canvas.getContext )
  {
      // Canvasから描画用のコンテキストを取得する
      var context = canvas.getContext( '2d' );
  }

</script>

canvasのサイズ

canvasの描画領域のサイズは、その要素のwidth、height属性で指定します。

<canvas width="100" height="100"></canvas>

これを要素のスタイルで指定した場合、表示上のサイズは変更されますが描画領域には反映されず、グラフィックが拡大/縮小されて表示されることになります。

<canvas style="width: 100px; height: 100px"></canvas>

width、height属性を適切に指定しなかった場合は、それぞれの既定値の300150になります。Properties - HTMLCanvasElement - Web APIs | MDN

スクリーン サイズに合うように自動調整

canvasの表示サイズをスクリーンに合わせるには、width:100%のようにCSSを用いて割合で指定します。しかしCSSで指定しただけでは、拡大/縮小されて表示されるだけです。Resize HTML5 canvas to fit window - Stack Overflow

<canvas style="width: 100%"></canvas>

これをスクリーン サイズに合うように調整するには、スクリプトでcanvasの描画領域のサイズを、その要素の表示領域のサイズに一致するように修正します。

canvas.width = canvas.offsetWidth;
// 描画処理

グラフィックを更新するときにはスクリーンのサイズが変更されていることを考慮して、このサイズの修正を毎回行います。

このサンプルは、ウィンドウの幅に合わせて調整されます。

Canvas対応のブラウザをお使いください。

Internet Explorer 9より前への対応

Internet Explorer 9より前はcanvas要素をサポートしないため、別途ライブラリを導入して対応させる必要があります。Browser compatibility

ExplorerCanvas
※ Release 3では、strokeTextなどのテキスト関係の処理はサポートされていません。

スクリプトをダウンロードしたら、それをcanvas要素より前で

<!--[if IE]><script type="text/javascript" src="excanvas.js"></script><![endif]-->

のように読み込みます。これがcanvasより後だとUnknown runtime errorとなります。

図形の描画

パスを使用した描画

描画はさまざまな形状を連結することで行われ、その一連の操作をパスと呼びます。パスはmoveTo()メソッドで分割することができ、そのように作成されたパスはサブパスと呼ばれます。作成したパスは、stroke()かfill()を実行することで描画されます。

パスの指定

作用 メソッド
パスの開始
beginPath()
CanvasRenderingContext2D.beginPath() - Web APIs | MDN
サブパスの開始
moveTo( x, y )
CanvasRenderingContext2D.moveTo() - Web APIs | MDN
パスを閉じる
closePath()
CanvasRenderingContext2D.closePath() - Web APIs | MDN
Paths - CanvasRenderingContext2D - Web APIs | MDN

形状の指定

形状 メソッド 処理後の現在の位置
直線
lineTo( x, y )
CanvasRenderingContext2D.lineTo() - Web APIs | MDN
指定の座標
矩形
rect( x, y, width, height )
座標原点 (0, 0)
円弧 中心点を指定
arc(
    x, y,
    radius,
    startAngle,
    endAngle,
    [ anticlockwise ]
    )
CanvasRenderingContext2D.arc() - Web APIs | MDN
弧の終了点
接点を指定※1
arcTo( x1, y1, x2, y2, radius )
曲線 2次ベジェ曲線
quadraticCurveTo(
    cp1x, cp1y,
    x, y
    )
終了点の座標
3次ベジェ曲線
bezierCurveTo(
    cp1x, cp1y,
    cp2x, cp2y,
    x, y
    )
※1 一部のブラウザはサポートしません。
context.beginPath();
context.moveTo( 100, 0 );
context.lineTo( 100, 100 );

context.moveTo( 0, 0 );
context.lineTo( 50, 100 );
context.lineTo( 0, 50 );
context.stroke();
Canvas対応のブラウザをお使いください。

円を描くメソッドはありませんが、arc()で0~2πまでの角度で円弧を描くことで円となります。

context.beginPath()
context.arc( 100, 100, 50, 0, 2*Math.PI );
context.stroke();

描画の実行

塗りつぶし メソッド
なし
stroke()
あり
fill()
Drawing paths - CanvasRenderingContext2D - Web APIs | MDN

パスを使用しない描画

以下のメソッドはパスに無関係に形状を作成し、描画を実行します。
※ JavaScriptの以前のバージョンでは、これらのメソッドの実行後にパスが削除されるようです。

形状
形状 塗りつぶし メソッド
矩形 なし
strokeRect( x, y, width, height )
あり
fillRect( x, y, width, height )
clearRect( x, y, width, height )
Drawing rectangles - CanvasRenderingContext2D - Web APIs | MDN
var context = canvas.getContext( '2d' );

context.fillRect( 10, 10, 50, 50 );
context.strokeRect( 80, 10, 50, 50 );
Canvas対応のブラウザをお使いください。

テキストの描画

テキストの描画は、IE9以降またはFirefox 3.5以降でサポートされています。Browser compatibility - Drawing text using a canvas - Web API Interfaces | MDN

塗りつぶし メソッド
なし
strokeText(
    textToDraw,
    x,
    y,
    [ maxWidth ]
    )
CanvasRenderingContext2D.strokeText() - Web APIs | MDN
あり
fillText(
    textToDraw,
    x,
    y,
    [ maxWidth ]
    )
CanvasRenderingContext2D.fillText() - Web APIs | MDN
Drawing text - CanvasRenderingContext2D - Web APIs | MDN
context.strokeText( 'strokeText', 10, 0 );
context.fillText( 'fillText', 10, 50 );
Canvas対応のブラウザをお使いください。

テキストの大きさの取得

measureText( textToMeasure )
CanvasRenderingContext2D.measureText() - Web APIs | MDN
context.measureText( 'a' ).width;      // 5
context.measureText( 'i' ).width;      // 2
context.measureText( 'sample' ).width; // 29

スタイルの変更

  • font
    • 10px sans-serif (既定)
  • textAlign
    • start (既定)
    • end
    • left
    • right
    • center
  • textBaseline
    • top
    • hanging
    • middle
    • alphabetic (既定)
    • ideographic
    • bottom
  • direction
    • ltr
    • rtl
    • inherit (既定)

描画方法

色やパターンの指定

塗りつぶさない描画の色は、strokeStyleプロパティに設定し、

context.strokeStyle = color;    // 指定色で描画:文字列
context.strokeStyle = gradient; // グラデーションで描画:CanvasGradientオブジェクト
context.strokeStyle = pattern;  // パターンで描画:CanvasPatternオブジェクト
CanvasRenderingContext2D.strokeStyle - Web APIs | MDN

塗りつぶす描画にはfillStyleに設定します。

context.fillStyle = color;
context.fillStyle = gradient;
context.fillStyle = pattern;
CanvasRenderingContext2D.fillStyle - Web APIs | MDN
var context = canvas.getContext( '2d' );

context.strokeStyle = 'blue';
context.fillStyle = 'red';

context.strokeRect( 10, 10, 50, 50 ); // 塗りつぶし なし
context.fillRect( 80, 10, 50, 50 );   // 塗りつぶし あり

context.beginPath();
context.moveTo( 150, 20 );
context.lineTo( 200, 50 );
context.lineTo( 250, 10 );

context.fill();   // 塗りつぶし あり
context.stroke(); // 塗りつぶし なし
Canvas対応のブラウザをお使いください。

色の指定

色の指定は、CSSと同様です。

context.fillStyle = 'rgb(255,0,0)';
context.fillStyle = 'rgb(100%,0%,0%)';
context.fillStyle = 'rgba(255,0,0,0.5)';

context.fillStyle = '#f00';
context.fillStyle = '#ff0000';

context.fillStyle = 'hsl(0,100%,50%)';
context.fillStyle = 'hsla(0,100%,50%,0.5)';
指定の順序

色の設定などは、現在のパスに対して適用されます。よってパスを作成中に色を変更すると、先に設定した色が新しい色で上書きされることになります。

間違った例
// パスを開始する
context.beginPath();
context.strokeStyle = 'red';  // 赤に設定

context.moveTo( 0, 10 );
context.lineTo( 100, 10 );

context.strokeStyle = 'blue'; // 青に設定
context.lineTo( 200, 10 );

// 描画の実行
context.stroke();

パスの作成中に色を設定し直しているため、後に設定した色ですべて描画されます。

実行結果:Canvas対応のブラウザをお使いください。

正しい例
// パスを開始する
context.beginPath();
context.strokeStyle = 'red';  // 赤に設定

context.moveTo( 0, 10 );
context.lineTo( 100, 10 );

// 描画の実行
context.stroke();

// パスを開始する
context.beginPath();
context.strokeStyle = 'blue'; // 青に設定

context.moveTo( 100, 10 );
context.lineTo( 200, 10 );

// 描画の実行
context.stroke();

色の再設定前に描画を実行し、パスを開始してから新しい色を設定します。

実行結果:Canvas対応のブラウザをお使いください。

グラデーションの指定

2つの色を変化させ、それをグラデーション (ぼかし) として描画できます。CanvasGradient - Web APIs | MDN

線形グラデーション

色を2点間で変化させるならば、createLinearGradient()を用います。

CanvasGradient ctx.createLinearGradient(x0, y0, x1, y1);
CanvasRenderingContext2D.createLinearGradient() - Web APIs | MDN
var context = canvas.getContext( '2d' );

var gradient = context.createLinearGradient( 20, 20, 80, 80 );
gradient.addColorStop( 0, 'blue' );
gradient.addColorStop( 1, 'red' );

context.fillStyle = gradient;
context.fillRect( 0, 0, 300, 100 );
Canvas対応のブラウザをお使いください。

CSSのlinear-gradient属性

円形グラデーション / 放射状グラデーション

色を2円間で変化させるならば、createRadialGradient()を用います。

CanvasGradient ctx.createRadialGradient(x0, y0, r0, x1, y1, r1);
CanvasRenderingContext2D.createRadialGradient() - Web APIs | MDN
var context = canvas.getContext( '2d' );

var gradient = context.createRadialGradient( 50, 50, 20, 60, 50, 40 );
gradient.addColorStop( 0, 'blue' );
gradient.addColorStop( 1, 'red' );

context.fillStyle = gradient;
context.fillRect( 0, 0, 300, 100 );
Canvas対応のブラウザをお使いください。

パターンの指定

画像を並べて、それをパターン (模様) として描画できます。CanvasPattern - Web APIs | MDN

CanvasPattern ctx.createPattern(image, repetition);
CanvasRenderingContext2D.createPattern() - Web APIs | MDN
var context = canvas.getContext( '2d' );

var image = new Image();
image.onload = function()
{
    var pattern = context.createPattern( image, 'repeat' );
    context.fillStyle = pattern;
    context.fillRect( 0, 0, 300, 100 );
}
image.src = 'sample.bmp';
Canvas対応のブラウザをお使いください。

線の幅、線の終端、線のつなぎ目

適用箇所 メソッド
lineWidth
終端 lineCap
結合方法 lineJoin

イベント

canvas要素に対するonclickやonmousemoveで、イベントを捕捉できます。

実行例

下の枠内でマウスポインタを移動させると、その位置に点を描画します。

Canvas対応のブラウザをお使いください。
canvas.onmousemove = function( event )
{
    var x = event.clientX + window.pageXOffset - this.offsetLeft;
    var y = event.clientY + window.pageYOffset - this.offsetTop;

    var context = this.getContext( '2d' );
    context.moveTo( x, y );
    context.beginPath()
    context.arc( x, y, 2, 0, 2 * Math.PI );
    context.fill();
}

画像の保存

ローカルへの保存

HTMLCanvasElement.toDataURL()で取得したURLをHTMLAnchorElement.downloadに設定することで、そのリンクのクリックによりダウンロードさせられます。javascript - Save canvas as jpg to desktop - Stack Overflow

サーバーへの保存

ローカルへの保存と同様にtoDataURL()で情報を取得し、それをサーバーへPOSTします。javascript - How to save a HTML5 Canvas as Image on a server - Stack Overflow