HTML Living Standard  第3部 Javascript 11 グラフィック


 

11 グラフィック(Canvas)

11.1  Canvas

canvas 要素は、WEBブラウザ上で動的にグラフィックを描画するための仕組みです。もともと Apple社が Safariの独自拡張として策定したものでしたが、現在はほとんどのブラウザ上で canvas 要素が利用できるようになっています。

11.1.1  Canvas の一般的な手順

Canvas では、HTML と JavaScript を組み合わせて描画内容を指定します。 Canvas による描画は、大まかに以下のような流れとなります。

  1. HTMLで、canvas 要素の幅と高さ、および、id名を指定する
  2. getElementById メソッドでHTMLと関連付けて、getContext メソッドで描画機能を有効にする
  3. Canvas のメソッドやプロパティを使用して、具体的な描画内容を Javascript で記述する

canvas 要素

canvas 要素の描画領域を定義する。HTML のタグとして記述します。

属性

属性名属性値説明必須
width1 ~描画領域の幅 (規定値:300)×
height1 ~描画領域の高さ (規定値:150)×

なお、描画領域の幅と高さは後からでも変更・参照することができます。

width、height プロパティ

canvas 要素のオブジェクトの持つ描画領域の幅または高さを定義・参照する。

属性

プロパティ説明
width1 ~描画領域の幅
height1 ~描画領域の高さ

記述例
<canvas id="c" width="200" height="100"></canvas>    <!-- 1.  <canvas>要素の幅と高さ、および、id名を指定する -->

<script>
var canvas = document.getElementById('c');
canvas.width = 300;    // 幅を 300 に変更
canvas.height = 200;   // 高さを 200 に変更
</script>

上記の例で canvas 要素は定義できましたが、Canvas に描画するためには、この後に、canvas 要素の getContext(contextId) メソッドを使ってコンテキストを取得しなければいけません。

Canvas に描画するためのメソッドは、このコンテキストが持っています。

canvas 要素のオブジェクト.getContext(contextId)

canvas 要素のコンテキストを取得する。getContext メソッドで得られるコンテキストはひとつだけです。何回行っても同じコンテキストが返ります。

引数 contextIdコンテキストオブジェクトの種類
 "2d": 2次元ベクタグラフィックを描くための標準的なAPIセット
戻り値canvas 要素のコンテキスト(未サポートな contextId ならば null)
記述例
<canvas id="c" width="200" height="100"></canvas>    <!-- 1.  <canvas>要素の幅と高さ、および、id名を指定する -->

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');    // 2.  2Dコンテキストを取得
                                          // 3.  これ以降に描画内容を記述
context.lineWidth = 5;                       // 線の太さを 5
context.strokeStyle = "red";
context.rect(50, 20, 100, 50);
context.stroke();                            // 赤の矩形
context.save();                              // 属性を保存
context.beginPath();
context.lineWidth = 1;                       // 線の太さを 1
context.strokeStyle = "green";
context.scale(10, 2);                        // X 軸方向に 10倍、 Y 軸方向に 2倍
context.arc(50, 50, 40, Math.PI , Math.PI*1.5);
context.stroke();                            // 緑の円弧
context.beginPath();
context.restore();                           // 属性を復帰
context.rect(250, 20, 100, 50);
context.stroke();                            // 赤の矩形
</script>
実行例

11.1.2  SVG との違い

Canvas は、上記の例のように描画領域は HTML の canvas 要素で確保しますが、実際の図形描画は Javascript で行います。それに対して、SVG(第1部 HTML5 13 グラフィックス(SVG))は基本として XML をベースとしたタグを記述します。

先の例と同じ図形を SVG で記述すると次のようになります。

記述例
<svg viewbox="0,0 500 100" width="500" height="100">
  <rect x="50" y="20" width="100" height="50" stroke="red" fill="none" stroke-width="5"/>     <!-- 赤の矩形 -->
  <path d="M50,10 A40,40 0 0 0 10,50" stroke="green" fill="none" transform="scale(10, 2)"/>   <!-- 緑の円弧 -->
  <rect x="250" y="20" width="100" height="50" stroke="red" fill="none" stroke-width="5"/>    <!-- 赤の矩形 -->
</svg>
実行例

Canvas と SVG との違い
CanvasSVG
描画形式ラスター(ビットマップ)形式(拡大するとギザギザが目立つ)ベクター形式
描画方式canvas 要素で描画領域(キャンバス)を確保し、JavaScriptを用いて描画する図形一つひとつが svg 要素の子要素として記載される
描画基本単位直線や曲線などの図形の構成部分円や矩形などの図形
イベントどの図形に対するイベントかを判定する必要がある個々の図形のタグに onclick のように記述できる
スタイルシート指定不可
利用性png、jpeg などのファイル形式で保存できる拡張子 svg として保存するとイメージファイルとして img 要素の src にも記述できる
パフォーマンス小さい多数の図形の描画に向く大きい少数の図形の描画に向く
アニメーション独自の機能としては持たない(アニメーション用のメソッドはない)独自の機能を持つ(アニメーション用のタグがある)

11.2  描画状態

線の種類や色などを変更するためのプロパティ、および図形を変形するためのメソッドについて説明します。

描画状態は次の要素から構成されます。

11.2.1  色

参考:Web カラー一覧

カラーネーム16進数

Canvas では、HTML と同じく、色を名称や16進数で指定することができます。

また、特別な色として、塗らないことを指示する none や 親要素の色を継承する inherit があります。


(1) 線の色 (strokeStyle)

strokeStyle プロパティは、線、テキストまたは要素の輪郭の色を定義します。

strokeStyle プロパティ

線、テキストまたは要素の輪郭の色を定義する。

次の値は代表的な指定方法です。詳しくは、「1.2.1 色」 を参照してください。 (規定値:黒色)

プロパティ説明
strokeStyle#rrggbb赤緑青、各色16進数2ケタ
カラーネーム代表的な色に付けられた名称(Web カラー一覧 参照)
rgb(rrr, ggg, bbb)赤緑青、各色10進数
CanvasGradient オブジェクトグラデーションを定義した CanvasGradient オブジェクト

記述例
<canvas id="c" width="400" height="100"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');

context.beginPath();              // 黒の横線
context.moveTo(30, 20);
context.lineTo(170, 20);
context.strokeStyle = "black";
context.stroke();

context.beginPath();              // 青の横線
context.moveTo(30, 50);
context.lineTo(170, 50);
context.strokeStyle = "#0000FF";
context.stroke();

context.beginPath();              // 赤の円
context.arc(230, 40, 30, 0, Math.PI*2);
context.strokeStyle = "rgb(255, 0, 0)";
context.stroke();

context.font = "32px 'MS Pゴシック'";     // 緑の文字列
context.strokeStyle = "green";
context.strokeText("文字列", 20, 100);

context.beginPath();              // グラデーション
context.moveTo(300, 20);
context.lineTo(400, 20);
var grad = context.createLinearGradient(300, 0, 400, 0);
grad.addColorStop(0.2, 'red');
grad.addColorStop(0.8, 'violet');
context.strokeStyle = grad;
context.lineWidth = 20;
context.stroke();
</script>
表示例

(2) 面の色 (fillStyle)

fillStyle プロパティは、面の色を定義します。つまり、塗りつぶす色を定義します。

fillStyle プロパティ

塗りつぶす面の色を定義する。

次の値は代表的な指定方法です。詳しくは、「1.2.1 色」 を参照してください。 (規定値:透明)

プロパティ説明
fillStyle#rrggbb赤緑青、各色16進数2ケタ
カラーネーム代表的ない色に付けられた名称(Web カラー一覧 参照)
rgb(rrr, ggg, bbb)赤緑青、各色10進数
CanvasGradient オブジェクトグラデーションを定義した CanvasGradient オブジェクト

記述例
<canvas id="c" width="400" height="100"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');
context.fillStyle = "blue";                   // 青の矩形
context.fillRect(30, 20, 140, 50);

context.arc(150, 40, 30, 0, Math.PI*2);       // 赤の円
context.fillStyle = "#FF0000";
context.fill();

context.font = "32px 'MS Pゴシック'";      // 緑の文字列
context.fillStyle = "rgb(0, 128, 0)";
context.fillText("文字列", 20, 80);

var grad =context.createLinearGradient(200, 0, 280, 0);  // グラデーション
grad.addColorStop(0.2, 'red');
grad.addColorStop(0.8, 'violet');
context.fillStyle = grad;
context.fillRect(200, 20, 80, 50);
</script>
表示例

11.2.2  透明度

(1) 透明度 (globalAlpha)

globalAlpha プロパティは、色の透明度を定義します。

globalAlpha プロパティ

線、テキスト、要素の輪郭または塗りつぶしの透明度を定義する。

プロパティ説明
globalAlpha0 ~ 1透明度 0(透明)~ 1(不透明) (規定値:1)
記述例
<canvas id="c" width="300" height="120"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');
context.fillStyle = "red";
context.fillRect(40, 10, 20, 99);
context.fillStyle = "blue";
context.fillRect(60, 10, 20, 99);
context.fillStyle = "green";
context.fillRect(80, 10, 20, 99);
context.fillStyle = "yellow";
context.globalAlpha = 0;
context.fillRect(20, 10, 80, 20);
context.globalAlpha = 0.2;
context.fillRect(20, 30, 80, 20);
context.globalAlpha = 0.4;
context.fillRect(20, 50, 80, 20);
context.globalAlpha = 0.6;
context.fillRect(20, 70, 80, 20);
context.globalAlpha = 0.8;
context.fillRect(20, 90, 80, 20);

context.globalAlpha = 0.4;
context.beginPath();
context.arc(175, 40, 30, 0, Math.PI*2);
context.fillStyle = "red";
context.fill();
context.beginPath();
context.arc(158, 70, 30, 0, Math.PI*2);
context.fillStyle = "blue";
context.fill();
context.beginPath();
context.arc(192, 70, 30, 0, Math.PI*2);
context.fillStyle = "green";
context.fill();
</script>
表示例

11.2.3  線種

線の太さや種類を設定します。

(1) 線の太さ (lineWidth)

lineWidth プロパティは、線の太さを定義します。

lineWidth プロパティ

線の太さを定義する。

プロパティ説明
lineWidth0 ~ 線の太さ (規定値:1)
記述例
<canvas id="c" width="300" height="100"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');
context.strokeStyle = "blue";
context.beginPath();
context.lineWidth = 1;     // 太さ 1
context.moveTo(30, 10);
context.lineTo(270, 10);
context.stroke();
context.beginPath();
context.lineWidth = 5;     // 太さ 5
context.moveTo(30, 30);
context.lineTo(270, 30);
context.stroke();
context.beginPath();
context.lineWidth = 10;    // 太さ 10
context.moveTo(30, 50);
context.lineTo(270, 50);
context.stroke();
context.beginPath();
context.lineWidth = 20;    // 太さ 20
context.moveTo(30, 80);
context.lineTo(270, 80);
context.stroke();
</script>

指定された座標を中央に線が引かれます。下の例では、分かりやすいように指定された座標で幅1の黄色い破線を引いています。

表示例

(2) 線の両端の形状 (lineCap)

lineCap プロパティは、線の両端の形状を定義します。

lineCap プロパティ

線の両端の形状を定義する。

プロパティ説明
lineCapbutt線の両端に何もつかない(そのまま)(規定値)
round線の両端に、直径が線の幅と同じとなる半円が付く
square線の両端に、線の半分の幅となる矩形が付く
記述例
<canvas id="c" width="200" height="100"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');
context.strokeStyle = "blue";
context.lineWidth = 20;
context.beginPath();
context.moveTo(30, 20);
context.lineTo(170, 20);
context.lineCap = "butt";    // 両端 そのまま
context.stroke();
context.beginPath();
context.moveTo(30, 50);
context.lineTo(170, 50);
context.lineCap = "round";   // 両端に半円
context.stroke();
context.beginPath();
context.moveTo(30, 80);
context.lineTo(170, 80);
context.lineCap = "square";  // 両端に矩形
context.stroke();
</script>

両端にライン・キャップが付きます。下の例では、分かりやすいように本来の幅で黄色い破線を引いています。

表示例

(3) 線の頂点の形状 (lineJoin、miterLimit)

lineJoin プロパティは、線の頂点の形状を定義します。

lineJoin プロパティ

線の頂点の形状を定義する。

プロパティ説明
lineJoinmiter鋭角(そのまま) (規定値)
round円形
bevel面取り(カット)
記述例
<canvas id="c" width="200" height="180"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');
context.strokeStyle = "blue";
context.lineWidth = 20;
context.beginPath();
context.moveTo(20, 20);
context.lineTo(80, 20);
context.lineTo(100, 50);
context.lineTo(120, 20);
context.lineTo(180, 20);
context.lineJoin = "miter";  // 鋭角(そのまま)
context.stroke();
context.beginPath();
context.moveTo(20, 70);
context.lineTo(80, 70);
context.lineTo(100, 100);
context.lineTo(120, 70);
context.lineTo(180, 70);
context.lineJoin = "round";  // 円形
context.stroke();
context.beginPath();
context.moveTo(20, 120);
context.lineTo(80, 120);
context.lineTo(100, 150);
context.lineTo(120, 120);
context.lineTo(180, 120);
context.lineJoin = "bevel";  // 面取り(カット)
context.stroke();
</script>

頂点の形状を指定しています。

表示例


miterLimit プロパティは、lineJoin="miter" のときの、鋭角な頂点を面取りする閾値を定義します。

miterLimit プロパティ

lineJoin="miter" のときの、鋭角な頂点を面取りする閾値を定義する。

プロパティ説明
miterLimit0 ~lineJoin="miter" のとき、鋭角すぎるとき面取りする閾値 (規定値:10.0)
(頂点が為す角度から計算された値が指定された値より大きいと面取りされる)
記述例
<canvas id="c" width="200" height="180"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');
context.strokeStyle = "blue";
context.lineWidth = 20;
context.lineJoin = "miter";
context.beginPath();
context.moveTo(20, 20);
context.lineTo(80, 20);
context.lineTo(100, 50);
context.lineTo(120, 20);
context.lineTo(180, 20);
context.miterLimit = 1;      // 面取り閾値
context.stroke();
context.beginPath();
context.moveTo(20, 70);
context.lineTo(80, 70);
context.lineTo(100, 100);
context.lineTo(120, 70);
context.lineTo(180, 70);
context.miterLimit = 1.802;  // 面取り閾値
context.stroke();
context.beginPath();
context.moveTo(20, 120);
context.lineTo(80, 120);
context.lineTo(100, 150);
context.lineTo(120, 120);
context.lineTo(180, 120);
context.miterLimit = 1.803;  // 面取り閾値
context.stroke();
</script>

miterLimit を指定して面取りをしています。一番上は3か所すべての頂点が面取りされていますが、真中は下向きの頂点だけです。

表示例

(4) 破線パターン (setLineDash、lineDashOffset)

setLineDash メソッドは、破線パターン(直線と空白の長さ)を定義します。この破線パターンを繰り返して線が引かれます。

コンテキスト.setLineDash(pattern)

破線パターン(直線と空白の長さ)を定義する。

引数 pattern破線パターンを設定した配列
 [実線(, 間隔, 実線, 間隔...)] の順に長さを指定する([] でも実線)
戻り値なし
記述例
<canvas id="c" width="200" height="120"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');
context.strokeStyle = "blue";
context.beginPath();
context.moveTo(30, 10);
context.lineTo(170, 10);
context.stroke();                              // 実線

context.beginPath();
context.moveTo(30, 30);
context.lineTo(170, 30);
context.setLineDash([2, 4]);                   // 点線
context.stroke();

context.beginPath();
context.moveTo(30, 50);
context.lineTo(170, 50);
context.setLineDash([10, 4]);                 // 破線
context.stroke();

context.beginPath();
context.moveTo(30, 70);
context.lineTo(170, 70);
context.setLineDash([2, 4, 10, 4]);           // 一点鎖線
context.stroke();

context.beginPath();
context.moveTo(30, 90);
context.lineTo(170, 90);
context.setLineDash([2, 2, 2, 4, 10, 4]);    // 二点鎖線
context.stroke();
</script>

破線パターンを指定して描いています。

表示例

lineDashOffset 属性は、破線パターンの開始位置を定義します。指定された位置の破線パターンから描きます。

lineDashOffset プロパティ

破線パターンの開始位置を定義する。

プロパティ説明
lineDashOffset0 ~破線パターンの開始位置 (規定値:0)
記述例
<canvas id="c" width="200" height="60"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');
context.strokeStyle = "blue";
context.setLineDash([20, 5]);                 // 破線
context.beginPath();
context.moveTo(30, 10);
context.lineTo(170, 10);
context.stroke();                // 繰り返しの開始 0

context.beginPath();
context.moveTo(30, 20);
context.lineTo(170, 20);
context.lineDashOffset = 5;      // 繰り返しの開始 5
context.stroke();

context.beginPath();
context.moveTo(30, 30);
context.lineTo(170, 30);
context.lineDashOffset = 10;     // 繰り返しの開始 10
context.stroke();

context.beginPath();
context.moveTo(30, 40);
context.lineTo(170, 40);
context.lineDashOffset = 15;     // 繰り返しの開始 15
context.stroke();

context.beginPath();
context.moveTo(30, 50);
context.lineTo(170, 50);
context.lineDashOffset = 20;     // 繰り返しの開始 20
context.stroke();
</script>

すべての線は 20 引いて 5 引かないの繰り返しです。ただし、、その繰り返しの開始を 5 ずつずらして描いています。

表示例

11.2.4  変形 (translate、scale、rotate、transform、setTransform)

図形に対して平行移動や回転などの変形(座標変換)が適用できます。

変形を適用する場合には、先に変形を指定してから図形を描画するという順序になります。変形を後から指定しても、先に描画した図形には適用されません。

また、translate、scale、rotate 関数、あるいはそれらの関数の組み合わせを1つの transform 関数で置き換えることもできます。

(1) 平行移動 (translate)

平行移動を表すメソッドで、指定した値の分だけ座標軸をその方向にずらします。

この後に描かれる図形はこのずらされた座標系を基準に描かれます。

コンテキスト.translate(tx, ty)

平行移動する。

transform(1, 0, 0, 1, tx, ty) と記述することもできる。

10tx
01ty
001

引数 tx水平方向の移動距離
ty垂直方向の移動距離
戻り値なし
記述例
<canvas id="c" width="200" height="60"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');
context.translate(40, 20);             // 座標軸を平行移動(右に 40、下に 20)
context.strokeStyle = "blue";
context.beginPath();
context.strokeRect(10, 10, 100, 50);   // 移動前の座標でいうと、左上が (50,30) という座標になる
</script>

グレイの線は、移動前の図形や座標軸(左上が移動前の原点)です。うすい青い線は移動後の座標軸です。移動後は、移動前の原点が(-40, -20)という座標になります。理解の助けになるように別途描いています。

表示例

(2) 拡大・縮小 (scale)

拡大・縮小を表すメソッドで、左上端を基準に、指定した値の分だけ座標軸方向に拡縮します。

この後に描かれる図形はこの倍率で描かれます。よって、scale(3,0.5) の後で元の倍率で描きたければ scale(1/3,1/0.5) とする必要があります。

コンテキスト.scale(sx, sy)

拡大・縮小する。

transform(sx, 0, 0, sy, 0, 0) と記述することもできる。

sx00
0sy0
001

引数 sx水平方向の拡縮率
sy垂直方向の拡縮率
戻り値なし

拡縮すると図形の線も軸方向に太くなったり細くなったりします。また、倍率としてマイナスの数値を指定すると図形の反転もできます。

記述例
<canvas id="c" width="500" height="200"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');
context.translate(100, 0);       // Y座標を右に寄せるために平行移動
context.strokeStyle = "blue";
context.scale(3, 1.5);        // 元の図形に対して、横 3倍、縦 1.5倍
context.beginPath();
context.arc(50, 50, 40, 0, Math.PI*2);
context.stroke();
context.beginPath();
context.scale(-1/3, 1/1.5);   // 元の図形に対して、横 -1倍、縦 1倍(左右反転)
context.moveTo(10, 110);
context.lineTo(90, 160);
context.lineTo(-10, 160);
context.closePath();
context.stroke();
</script>

グレイの線などは、拡縮前の図形です。理解の助けになるように別途描いています。

表示例

(3) 回転 (rotate)

回転を表すメソッドで、座標の原点を中心に座標軸を指定した値の分だけ回転します。

コンテキスト.rotate(angle)

座標の原点を中心に回転する。

transform(cos(angle), sin(angle), -sin(angle), cos(angle), -cos(angle)+sin(angle), -sin(angle)-cos(angle)) と記述することもできる。

cos(angle)-sin(angle)-cos(angle)+sin(angle)
sin(angle)cos(angle)-sin(angle)-cos(angle)
001

引数 angle回転角(ラジアン:時計回りが正)
戻り値なし

座標の原点を中心に回転します。

したがって、特定の図形などを回転させたければ、回転の中心を座標の原点にする必要があります。

記述例
<canvas id="c" width="500" height="180"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');

context.rotate(Math.PI/4);        // 時計回りに 45度回転
context.strokeStyle = "blue";
context.strokeRect(10, 10, 100, 50);
</script>

グレイの線は、回転前の図形と座標軸です。うすい青い線は回転後の座標軸です。理解の助けになるように別途描いています。

表示例

図形の中心(対角線の交点)で回転させたい場合は、回転の中心(座標の原点)を図形の中心に移動する必要があります。

記述例
<canvas id="c" width="500" height="180"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');
const X = 10;                      // 左上 X座標
const Y = 10;                      // 左上 Y座標
const WIDTH = 100;                 // 矩形の幅
const HEIGHT = 50;                 // 矩形の高さ
const CX = X + WIDTH / 2;          // 矩形の中心(対角線の交点)の X座標
const CY = Y + HEIGHT / 2;         // 矩形の中心(対角線の交点)の Y座標
context.translate(CX, CY);       // 図形の中心で回転させるために、座標の原点を矩形の中心に平行移動
context.rotate(Math.PI/4);       // 時計回りに 45度回転
context.strokeStyle = "blue";
context.strokeRect(X - CX, Y - CY, WIDTH, HEIGHT);     // 座標の原点を平行移動したため、矩形の左上座標は負になる
</script>

グレイの線は、回転前の図形と座標軸です。うすい青い線は回転後の座標軸です。理解の助けになるように別途描いています。

表示例

(4) 座標変換行列 (transform、setTransform)

図形を描画するときに適用する座標の変換行列を作成します。

変形を適用する場合には、先に変形行列を指定してから図形を描画するという順序になります。 変形行列を後から指定しても、先に描画した図形には影響しません。

コンテキスト.transform(a, b, c, d, e, f)

図形を描画するときに適用する座標の変換行列を現在の変換行列にかけ合わせることによって作成する。

translate、scale、rotate の各関数は transform 関数で記述することができる。

複数の関数を指定した場合は、それぞれの行列の積で求まる値が transform 関数の引数になる。

引数 
ace
bdf
001
aX軸方向の拡縮率(変形しない場合は 1)
bY軸方向の傾斜(変形しない場合は 0)
cX軸方向の傾斜(変形しない場合は 0)
dY軸方向の拡縮率(変形しない場合は 1)
eY軸方向の移動距離(変形しない場合は 0)
fX軸方向の移動距離(変形しない場合は 0)
戻り値なし

コンテキスト.setTransform(a, b, c, d, e, f)

図形を描画するときに適用する座標の変換行列を新たに作成する。

translate、scale、rotate の各関数は setTransform 関数で記述することができる。

複数の関数を指定した場合は、それぞれの行列の積で求まる値が setTransform 関数の引数になる。

引数 
ace
bdf
001
aX軸方向の拡縮率(変形しない場合は 1)
bY軸方向の傾斜(変形しない場合は 0)
cX軸方向の傾斜(変形しない場合は 0)
dY軸方向の拡縮率(変形しない場合は 1)
eY軸方向の移動距離(変形しない場合は 0)
fX軸方向の移動距離(変形しない場合は 0)
戻り値なし

setTransform は、それまでに設定されている変換行列があったとしてもそれを破棄し新たに作成します。それに対して、transform は、それまでに設定されている変換行列があったらそれに掛けあわせて新たな変換行列を作成します。

したがって、次の例はどちらの円も結果的に、円の中心で座標軸を30度回転し、平行方向に2倍 垂直方向に半分にしたものになっています。

記述例
<canvas id="c1" width="100" height="60"></canvas><canvas id="c2" width="100" height="60"></canvas>

<script>
var canvas1 = document.getElementById('c1');
var context1 = canvas1.getContext('2d');
context1.setTransform(1, 0, 0, 1, 50, 30);                     // translate(50, 30) 右に50、下に30
context1.transform(0.866, 0.5, -0.5, 0.866, -0.366, -1.366);   // rotate(Math.PI/6) 30°回転
context1.transform(2, 0, 0, 0.5, 0, 0);                        // scale(2, 0.5)     平行方向に2倍、垂直方向に半分
context1.beginPath();
context1.strokeStyle = "blue";
context1.arc(0, 0, 20, 0, Math.PI*2);  // 中心(0, 0)、半径 20 の円
context1.stroke();

var canvas2 = document.getElementById('c2');
var context2 = canvas2.getContext('2d');
context2.setTransform(1.732, 1, -0.25, 0.433, 49.634, 28.634);  // context1 と同じ処理
context2.beginPath();
context2.strokeStyle = "red";
context2.arc(0, 0, 20, 0, Math.PI*2);  // 中心(0, 0)、半径 20 の円
context2.stroke();
</script>
表示例

なお、context1 の

 setTransform(1, 0, 0, 1, 50, 30)

 transform(0.866, 0.5, -0.5, 0.866, -0.366, -1.366)

 transform(2, 0, 0, 0.5, 0, 0)

は、これらが表す行列の積になります。 これを式で表すと

 
1050
0130
001
*
0.866-0.5-0.366
0.50.866-1.366
001
*
200
00.50
001
=
0.866-0.549.634
0.50.86628.634
001
*
200
00.50
001
=
1.732-0.2549.634
10.43328.634
001

よって、context2 の

 setTransform(1.732, 1, -0.25, 0.433, 49.634, 28.634) になります。





なお、SVG にはあるんですが、Canvas にはない「傾斜」についても説明しておきます。

SVG では、横方向の傾斜を skewX、 縦方向の傾斜を skewY で実現しています。


○ 横方向の傾斜 (skewX)

Y 軸を指定した角度だけ傾け、横方向に傾斜させます。(Canvas のメソッドではありません。)

skewX(angle)

横方向に傾斜する。

引数 angle傾斜角度(ラジアン:X 軸の正方向が正)
戻り値なし

記述例
<canvas id="c" width="500" height="140"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');

function skewX(angle) {
  context.setTransform(1, 0, Math.tan(angle), 1, 0, 0);
}

context.beginPath();
skewX(Math.PI/6);    // 30°傾ける
context.strokeStyle = "blue";
context.arc(50, 50, 40, 0, Math.PI*2);       // 円描画
context.stroke();
</script>

グレイの線は、傾斜前の座標軸や図形です。うすい青い線は傾斜後の座標軸です。理解の助けになるように別途描いています。

表示例


○ 縦方向の傾斜 (skewY)

X 軸を指定した角度だけ傾け、縦方向に傾斜させます。(Canvas のメソッドではありません。)

skewY(angle)

縦方向に傾斜する。

引数 angle傾斜角度(ラジアン:Y 軸の負方向が正)
戻り値なし

記述例
<canvas id="c" width="500" height="160"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');

function skewY(angle) {
  context.setTransform(1, Math.tan(angle), 0, 1, 0, 0);
}

context.beginPath();
skewY(Math.PI/6);    // 30°傾ける
context.strokeStyle = "blue";
context.arc(50, 50, 40, 0, Math.PI*2);       // 円描画
context.stroke();
</script>

グレイの線は、傾斜前の座標軸や図形です。うすい青い線は傾斜後の座標軸です。理解の助けになるように別途描いています。

表示例


メソッドの組み合わせ時の注意

メソッドを組み合わせた場合はその順番によって変形後の図形が変わります。

次の例は、先に平行移動させてから回転させています。

記述例
<canvas id="c" width="500" height="160"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');

const X = 10;                   // 左上 X座標
const Y = 10;                   // 左上 Y座標
const WIDTH = 100;              // 矩形の幅
const HEIGHT = 50;              // 矩形の高さ
const CX = X + WIDTH / 2;       // 矩形の中心(対角線の交点)の X座標
const CY = Y + HEIGHT / 2;      // 矩形の中心(対角線の交点)の Y座標
context.translate(40, 20);       // 平行移動
context.translate(CX, CY);       // 図形の中心で回転させるために座標軸を平行移動
context.rotate(Math.PI/4);       // 時計回りに 45°回転
context.strokeStyle = "blue";
context.strokeRect(X - CX, Y - CY, WIDTH, HEIGHT);       // 矩形描画
</script>

グレイの線は、変形前の図形と座標軸です。うすい青い線は移動後の座標軸などです。理解の助けになるように別途描いています。

表示例

次の例は、先に回転させてから平行移動させています。回転後は X 軸、Y 軸の方向も回転していることに注意してください。

記述例
<canvas id="c" width="500" height="200"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');
context.translate(20, 20);       // 座標軸を描けるように平行移動

const X = 10;                   // 左上 X座標
const Y = 10;                   // 左上 Y座標
const WIDTH = 100;              // 矩形の幅
const HEIGHT = 50;              // 矩形の高さ
const CX = X + WIDTH / 2;       // 矩形の中心(対角線の交点)の X座標
const CY = Y + HEIGHT / 2;      // 矩形の中心(対角線の交点)の Y座標
context.translate(CX, CY);       // 図形の中心で回転させるために座標軸を平行移動
context.rotate(Math.PI/4);       // 時計回りに 45°回転
context.translate(40, 20);       // 平行移動
context.strokeStyle = "blue";
context.strokeRect(X - CX, Y - CY, WIDTH, HEIGHT);       // 矩形描画
</script>

グレイの線は、変形前の図形と座標軸です。うすい青い線は回転後の座標軸などです。理解の助けになるように別途描いています。

表示例

11.2.5  影

表示する図形や文字列に影を付ける際に使用します。

(1) 影の色 (shadowColor)

影の色を指定します。

shadowColor プロパティ

影の色を定義する。

次の値は代表的な指定方法です。詳しくは、「1.2.1 色」 を参照してください。 (規定値:透明)

属性

プロパティ説明
shadowColor#rrggbb赤緑青、各色16進数2ケタ
カラーネーム代表的ない色に付けられた名称(Web カラー一覧 参照)
rgb(rrr, ggg, bbb)赤緑青、各色10進数
記述例
<canvas id="c" width="600" height="80"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');
context.shadowOffsetX = 5;    //横に5pxずらす
context.shadowOffsetY = 3;    //縦に3pxずらす

context.strokeStyle = "blue";                 // 青の矩形
context.shadowColor = "black";                // 黒の影
context.fillRect(30, 20, 140, 50);

context.font = "32px 'MS Pゴシック'";
context.fillStyle = "yellow";                 // 黄色の文字列
context.shadowColor = "rgb(0, 128, 0)";       // 緑の影
context.fillText("文字列", 40, 50);
</script>
表示例

(2) 影のぼかし (shadowBlur)

影のぼかしレベルを指定します(ぼかしレベルであって、ぼかしの範囲ではありません)。

shadowBlur プロパティ

影のぼかしレベルを定義する。

属性

プロパティ説明
shadowBlur0 ~ぼかしレベル (規定値:0)
記述例
<canvas id="c" width="800" height="130"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');
context.shadowOffsetX = 10;    //横に10pxずらす
context.shadowOffsetY = 10;    //縦に10pxずらす

context.strokeStyle = "blue";                 // 青
context.shadowColor = "black";                // 黒の影
context.font = "32px 'MS Pゴシック'";

context.shadowBlur = 0;
context.fillRect(0, 10, 50, 50);
context.fillText("文字列", 0, 100);

context.shadowBlur = 3;
context.fillRect(120, 10, 50, 50);
context.fillText("文字列", 120, 100);

context.shadowBlur = 5;
context.fillRect(240, 10, 50, 50);
context.fillText("文字列", 240, 100);

context.shadowBlur = 10;
context.fillRect(360, 10, 50, 50);
context.fillText("文字列", 360, 100);

context.shadowBlur = 15;
context.fillRect(480, 10, 50, 50);
context.fillText("文字列", 480, 100);
</script>

左から右に向かって、順にぼかしを強くしています。

表示例

(3) 影の位置 (shadowOffsetX、shadowOffsetY)

影の位置(影を付ける図形からの隔たり)を指定します。

shadowOffsetX、shadowOffsetY プロパティ

影の位置を定義する。

属性

プロパティ説明
shadowOffsetX数値影を付ける図形からの水平方向の隔たり (規定値:0)
shadowOffsetY数値影を付ける図形からの垂直方向の隔たり (規定値:0)
記述例
<canvas id="c" width="800" height="150"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');
context.strokeStyle = "blue";                 // 青
context.shadowColor = "black";                // 黒の影
context.font = "32px 'MS Pゴシック'";
context.shadowBlur = 1;

context.shadowOffsetX = 0;    //横に0pxずらす
context.shadowOffsetY = 0;    //縦に0pxずらす
context.fillRect(0, 10, 50, 50);
context.fillText("文字列", 0, 100);

context.shadowOffsetX = 1;    //横に1pxずらす
context.shadowOffsetY = 1;    //縦に1pxずらす
context.fillRect(120, 10, 50, 50);
context.fillText("文字列", 120, 100);

context.shadowOffsetX = 3;    //横に3pxずらす
context.shadowOffsetY = 3;    //縦に3pxずらす
context.fillRect(240, 10, 50, 50);
context.fillText("文字列", 240, 100);

context.shadowOffsetX = 5;    //横に5pxずらす
context.shadowOffsetY = 5;    //縦に5pxずらす
context.fillRect(360, 10, 50, 50);
context.fillText("文字列", 360, 100);

context.translate(525, 15);       // 座標の原点(回転の中心)をずらす
context.rotate(Math.PI/6);        // 時計回りに 30度回転
context.fillRect(0, 0, 50, 50);
context.fillText("文字列", 0, 85);
</script>

左から右に向かって、順に隔たりを多くしています。この例では、shadowOffsetX、shadowOffsetY に同じ値を設定していますが、もちろん異なる値でも構いません。

また、図形に変形を加えても影には影響を与えません。影の隔たりはあくまで、水平方向と垂直方向です(変形後の X軸、Y軸方向ではありません)。

表示例

11.2.6  状態の保存と復元

プロパティの状況を保存(save)し、一時的に変更した後、保存した状態に戻す(restore)ことができます。このとき、restore すると最後に save した状態はなくなります。

save と restore は、ネストしていても構いませんが、restore したときに戻る状態は最後に save したものになります。そして、もう一度 restore すると、もししていればその前に save した状態に戻ります。

(1) 保存 (save)

現在の状態をスタックの最後に加えます。保存される状態には次のものがあります。

  • 現在の変換マトリックス
  • 現在のクリップ領域
  • 次の属性の現在の値: strokeStyle, fillStyle, globalAlpha, lineWidth, lineCap, lineJoin, miterLimit, shadowOffsetX, shadowOffsetY, shadowBlur, shadowColor, globalCompositeOperation, font, textAlign, textBaseline

コンテキスト.save()

現在の状態をスタックの最後に加える。

引数 なし
戻り値なし

(2) 復元 (restore)

スタックから最後状態を取り出し、現在の状態に設定します(現在の状態が取り出した状態に変更されます)。保存されている状態には次のものがあります。

  • 現在の変換マトリックス
  • 現在のクリップ領域
  • 次の属性の現在の値: strokeStyle, fillStyle, globalAlpha, lineWidth, lineCap, lineJoin, miterLimit, shadowOffsetX, shadowOffsetY, shadowBlur, shadowColor, globalCompositeOperation, font, textAlign, textBaseline

コンテキスト.restore()

スタックから最後状態を取り出し、現在の状態に設定する。

引数 なし
戻り値なし
記述例
<canvas id="c" width="600" height="80"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');
context.strokeStyle = "blue";              // 青色
context.save();                                                      // 状態の保存
context.beginPath();
context.moveTo(0, 10);
context.lineTo(100, 10);
context.stroke();

context.strokeStyle = "green";             // 緑色
context.save();                                                      // 状態の保存
context.beginPath();
context.moveTo(100, 10);
context.lineTo(200, 10);
context.stroke();

context.lineWidth = 5;                     // 太さ 5
context.save();                                                      // 状態の保存
context.beginPath();
context.moveTo(200, 10);
context.lineTo(300, 10);
context.stroke();

context.setLineDash([10, 4]);              // 破線
context.beginPath();
context.moveTo(300, 10);
context.lineTo(300, 60);
context.stroke();

context.restore();                                                   // 状態の復元(実線)
context.beginPath();
context.moveTo(300, 60);
context.lineTo(400, 60);
context.stroke();

context.restore();                                                   // 状態の復元(太さ 1)
context.beginPath();
context.moveTo(400, 60);
context.lineTo(500, 60);
context.stroke();

context.restore();                                                   // 状態の復元(青色)
context.beginPath();
context.moveTo(500, 60);
context.lineTo(600, 60);
context.stroke();
</script>
表示例

11.3  矩形

矩形を作成するために使用します。

11.3.1  矩形の枠 (strokeRect)

矩形の枠(塗りつぶさない線のみ)を描きます。

コンテキスト.strokeRect(x, y, width, height)

strokeStyle 属性で指定された色などを使用して、矩形を描く(塗りつぶさない)。

引数 x矩形の左上点の X 座標
y矩形の左上点の Y 座標
width矩形の幅
height矩形の高さ
戻り値なし
記述例
<canvas id="c" width="500" height="140"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');
context.strokeStyle = "blue";
context.strokeRect(10, 30, 100, 50);
context.lineWidth = 5;
context.strokeRect(120, 30, 100, 50);
context.setLineDash([10, 2]);
context.strokeRect(230, 30, 100, 50);
context.translate(390, 55);
context.rotate(-30*Math.PI/180);
context.strokeRect(-50, -25, 100, 50);
</script>

左側は枠のみ、2列目は線を太くしています。3列目は破線に変え、4列目は回転させています。

表示例

11.3.2  矩形の塗りつぶし (fillRect)

矩形を塗りつぶして描きます。

コンテキスト.fillRect(x, y, width, height)

fillStyle 属性で指定された色を使用して、矩形を塗りつぶす。

引数 x矩形の左上点の X 座標
y矩形の左上点の Y 座標
width矩形の幅
height矩形の高さ
戻り値なし
記述例
<canvas id="c" width="500" height="140"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');
context.fillStyle = "blue";
context.fillRect(10, 30, 100, 50);
context.translate(170, 55);
context.rotate(-30*Math.PI/180);
context.fillRect(-50, -25, 100, 50);
</script>

左側は単純に塗りつぶし、2列目は回転させています。

表示例

11.3.3  矩形の消去 (clearRect)

矩形で切り抜き透明にします。切り抜かれた後の色は <canvas> の背景色になります。

<canvas> の背景色で矩形を塗りつぶすのと同じです。

コンテキスト.clearRect(x, y, width, height)

矩形の形で切り抜き透明にする

引数 x矩形の左上点の X 座標
y矩形の左上点の Y 座標
width矩形の幅
height矩形の高さ
戻り値なし
記述例
<canvas id="c" width="400" height="120" style="background-color:yellow;"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');
context.fillStyle = "blue";
context.fillRect(0, 10, 300, 100);
context.clearRect(10, 30, 100, 50);
context.translate(170, 55);
context.rotate(-30*Math.PI/180);
context.clearRect(-50, -25, 100, 50);
</script>

左側は単純に消去し、2列目は回転させた矩形の形で消去しています。ともに青い色が消えて、<convas> 要素の背景色である黄色が見えるようになりました。

表示例

11.4  パス

パスを使用していろいろな図形を定義するために使用します。

Canvas のコンテキストには必ず現在のパスが 1つあります。

パスは、0 個以上のサブパスのリストを持ちます。それぞれのサブパスは、1 つ以上の地点のリストから構成され、直線や曲線で接続されます。そして、サブパスが閉じられているか否かを表すフラグから構成されます。閉じられたサブパスとは、サブパスの終点がサブパスの始点に直線で接続されたものです。

コンテキストが生成されたときには、パスにはサブパスが一つもありません。パスを作成するには、moveTo、lineTo、quadricCurveTo、bezierCurveTo、arcTo、arc を使用します。

また、パスを定義しただけでは図形は描かれません。stroke、fill を使用して枠を描いたり塗りつぶしたりする必要があります。

ちなみに、「11.3 矩形」で説明したメソッドではサブパスは作られません。

11.4.1  パス (beginPath、closePath、moveTo)

パスの開始と終了を宣言するために使用します。

(1) パスを開始する (beginPath)

パスの開始を宣言します。つまり、サブパスが 1つもない状態にします。

コンテキスト.beginPath()

パスの開始を宣言する

引数 なし
戻り値なし
記述例
<canvas id="c" width="300" height="140"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');
context.fillStyle = "blue";
context.beginPath();           // 左側
context.rect(10, 10, 100, 50);
context.arc(60, 100, 30, 0, Math.PI*2);
context.stroke();    // 描画

context.beginPath();           // 右側
context.rect(120, 10, 100, 50);
context.stroke();    // 描画
context.beginPath();              // ここで新たなパスになる
context.arc(170, 100, 30, 0, Math.PI*2);
context.stroke();    // 描画
</script>

左側は rect と arc の間に beginPath がありませんので、連結した一つのパスと見なされ、rect の終点と arc の始点との間に直線が引かれています。

右側は rect と arc の間に beginPath がありますので、一度パスが閉じて、arc から新たなパスが始まったとみなされます。したがって、rect の後に stroke で描画しておく必要があります。

表示例

(2) パスを閉じる (closePath)

パスの終点から始点に向かって直線が引かれたものと見なし、閉じた図形にします。

もし最後の直線が必要ないのなら、次のパスを開始するときも closePath はいりません。closePath なしに、beginPath を実行します。

なお、closePath を実行したら、自動的に新たなパスが開始されたと解釈されるので、beginPath は必要ありません。

コンテキスト.closePath()

パスの終点から始点に向かって直線が引き閉じた図形にする

引数 なし
戻り値なし
記述例
<canvas id="c" width="300" height="60"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');
context.fillStyle = "blue";
context.beginPath();           // 左側
context.moveTo(60, 10);
context.lineTo(10, 50);
context.lineTo(80, 50);
context.stroke();    // 描画

context.beginPath();           // 右側
context.moveTo(160, 10);
context.lineTo(110, 50);
context.lineTo(180, 50);
context.closePath();      // 終点から始点に向かって直線が引く
context.stroke();    // 描画
</script>

左側は closePath がありませんので、終点から始点に向かって直線が引かれず、図形は閉じません。

右側は closePath がありますので、終点から始点に向かって直線が引かれ、図形は閉じます。

表示例

(3) サブパスの始点を指定する (moveTo)

サブパスの開始座標を指定します。

ただし、rect などのような閉じた図形を定義するメソッドもありますので、moveTo が絶対に必要なわけではありません。

コンテキスト.moveTo(x, y)

サブパスの開始座標を指定する

引数 x水平方向の座標
y垂直方向の座標
戻り値なし
記述例
<canvas id="c" width="300" height="60"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');
context.fillStyle = "blue";
context.beginPath();
context.moveTo(10, 30);
context.lineTo(110, 30);
context.moveTo(60, 10);
context.lineTo(60, 80);
context.stroke();
</script>

(110, 30) から (60, 10) には直線が引かれません。

表示例

11.4.2  描画 (stroke、fill)

作成されたパスに従って図形を描画します。

(1) 図形の枠を描画する (stroke)

作成されたパスに従って図形の枠(輪郭のみで塗りつぶしません)を描画します。

コンテキスト.stroke()

作成されたパスに従って図形の枠を描画する

引数 なし
戻り値なし
記述例
<canvas id="c" width="300" height="120"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');

function rect(x, y, w, h) {
  context.beginPath();
  context.moveTo(x, y);
  context.lineTo(x + w, y);
  context.lineTo(x + w, y + h);
  context.lineTo(x, y + h);
  context.closePath();
}

context.strokeStyle = "blue";
context.rect(10, 30, 100, 50);    // コンテキストのメソッド
context.stroke();

rect(120, 10, 100, 50);           // パスを定義した関数
context.stroke();
</script>
表示例

(2) 図形を塗りつぶす (fill)

作成されたパスや塗り分けルールに従って図形を塗りつぶして描画します。

コンテキスト.fill([fillRule])

作成されたパスや塗り分けルールに従って図形を塗りつぶして描画する

引数 fillRule塗りつぶしルール
nonzero全面塗りつぶし(規定値)
evenodd塗り分け
戻り値なし
記述例
<canvas id="c" width="300" height="120"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');

function rect(x, y, w, h) {
  context.beginPath();
  context.moveTo(x, y);
  context.lineTo(x + w, y);
  context.lineTo(x + w, y + h);
  context.lineTo(x, y + h);
  context.closePath();
}

context.fillStyle = "blue";
context.rect(10, 30, 100, 50);    // コンテキストのメソッド
context.fill();

rect(230, 30, 100, 50);           // パスを定義した関数
context.fill();
</script>
表示例

fillRule は、塗り分けのルールを指定します。塗り分けは、折れ線で囲まれた領域内から外に向かって線を引いて、折線と交わるのが奇数本ならば塗りつぶし、そうでないなら塗りつぶさないという方式で行われています。

記述例
<canvas id="c" width="300" height="120"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');
context.strokeStyle = "blue";
context.fillStyle = "lightgreen";
context.moveTo(10, 10);
context.lineTo(110, 10);
context.lineTo(110, 110);
context.lineTo(10, 110);
context.lineTo(85, 35);
context.lineTo(110, 110);
context.closePath();
context.fill();                  // 全面塗りつぶし
context.stroke();

context.moveTo(150, 10);
context.lineTo(250, 10);
context.lineTo(250, 110);
context.lineTo(150, 110);
context.lineTo(225, 35);
context.lineTo(250, 110);
context.closePath();
context.fill("evenodd");         // 塗り分け
context.stroke();
</script>

左側は全面を塗りつぶしていて(nonzero)、右側は塗り分けています(evenodd)。

表示例

fillRule を指定することによって、全面塗りつぶすか、塗り分けをするかを指定することができます。

evenodd(塗り分け)は、lineTo や arc で描かれた線に囲まれた領域内から外に向かって線を引いて、交わる線が奇数本ならば塗りつぶし、そうでないなら塗りつぶさないという方式で行われています。

nonzero(全面塗りつぶし)の場合は基本的にすべてを塗りつぶしますが、左下の例のように nonzero であっても塗りわけが行われることがあります。

交わる線の向きが左から右のものと右から左のものとが同数のときは塗りつぶされません。

矢印は lineTo や arc で指定された線の描かれる向きです。別途描いています。

記述例
<canvas id="c" width="400" height="180"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');
context.strokeStyle = "blue";
context.fillStyle = "lightgreen";

context.beginPath();
context.moveTo(110, 30);
context.lineTo(190, 30);
context.lineTo(190, 170);
context.lineTo(110, 170);
context.closePath();

context.moveTo(170, 70);
context.arc(150, 70, 20, 0, Math.PI*2, false);    // 時計回り
context.moveTo(170, 130);
context.arc(150, 130, 20, 0, Math.PI*2, true);    // 反時計回り

context.fill("nonzero");         // 全面塗りつぶし
context.stroke();

context.beginPath();
context.moveTo(210, 30);
context.lineTo(290, 30);
context.lineTo(290, 170);
context.lineTo(210, 170);
context.closePath();

context.moveTo(270, 70);
context.arc(250, 70, 20, 0, Math.PI*2, false);    // 時計回り
context.moveTo(270, 130);
context.arc(250, 130, 20, 0, Math.PI*2, true);    // 反時計回り

context.fill("evenodd");         // 塗り分け
context.stroke();
</script>
表示例

真ん中に穴を開けて背景が表示されるようにすることもできます。

記述例
<canvas id="c" width="400" height="120"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');

function draw() {
  var img = document.getElementById('bear');
  context.drawImage(img, 100, 10);        // そのままの大きさ
  context.fillStyle = "blue";
  context.beginPath();
  context.moveTo(100, 10);
  context.lineTo(180, 10);
  context.lineTo(180, 90);
  context.lineTo(100, 90);
  context.closePath();

  context.moveTo(120, 75);
  context.translate(80, 0);
  context.scale(25/40, 1);
  context.arc(100, 60, 40, Math.PI*1/8, Math.PI*7/8, true);
  context.closePath();
  context.fill("evenodd");         // 塗り分け
}
</script>

<img id="bear" src="bear.png" width="64" height="64" style="display:none;" onLoad="draw()">
表示例

11.4.3  矩形 (rect)

矩形を作成する際に使用します。

strokeRect との違いはサブパスが生成されることです。rect だけでは図形の描画はされません。

コンテキスト.rect(x, y, w, h)

矩形を指定する

引数 x矩形の左上の X座標
y矩形の左上の Y座標
w矩形の幅
h矩形の高さ
戻り値なし
記述例
<canvas id="c" width="500" height="150"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');
context.strokeStyle = "blue";
context.fillStyle = "yellow";
context.rect(10, 10, 100, 50);
context.stroke();        // 枠を描画

context.beginPath();
context.rect(10, 70, 100, 50);
context.fill();          // 塗りつぶし

context.beginPath();
context.lineWidth = 5;             // 太さ 5
context.rect(120, 10, 100, 50);
context.stroke();        // 枠を描画

context.beginPath();
context.rect(120, 70, 100, 50);
context.fill();          // 塗りつぶし
context.stroke();        // 枠を描画

context.beginPath();
context.setLineDash([10, 4]);              // 破線
context.rect(230, 10, 100, 50);
context.stroke();        // 枠を描画

context.setLineDash([]);                   // 実線
context.beginPath();
context.rect(230, 70, 100, 50);
context.stroke();        // 枠を描画
context.fill();          // 塗りつぶし
</script>

上段左から、細い枠、太い枠、太い破線の枠(太さの指定が引き継がれています)

下段左から、塗りつぶし、塗りつぶしと枠、枠と塗りつぶし(左とは順序が逆)です。

表示例

11.4.4  円弧 (arc)

円弧を作成する際に使用します。

コンテキスト.arc(x, y, r, startAngle, endAngle[, anticlockwise])

円弧を指定する

引数 x円弧の中心の X座標
y円弧の中心の Y座標
r円弧の半径
startAngle開始角度ラジアン:X 軸の正の領域から時計回り
endAngle終了角度
anticlockwise描画の向き
true反時計回り
false時計回り(規定値)
戻り値なし
記述例
<canvas id="c" width="500" height="150"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');
context.strokeStyle = "blue";
context.fillStyle = "yellow";
context.arc(40, 40, 30, Math.PI/3, -Math.PI/6);
context.stroke();        // 枠を描画

context.beginPath();
context.arc(40, 110, 30, Math.PI/3, -Math.PI/6);
context.fill();          // 塗りつぶし

context.lineWidth = 5;             // 太さ 5
context.beginPath();
context.arc(110, 40, 30, Math.PI/3, -Math.PI/6);
context.stroke();        // 枠を描画

context.beginPath();
context.arc(110, 110, 30, Math.PI/3, -Math.PI/6);
context.fill();          // 塗りつぶし
context.stroke();        // 枠を描画

context.setLineDash([10, 4]);              // 破線
context.beginPath();
context.arc(180, 40, 30, Math.PI/3, -Math.PI/6);
context.stroke();        // 枠を描画

context.setLineDash([]);                   // 実線
context.beginPath();
context.arc(180, 110, 30, Math.PI/3, -Math.PI/6);
context.stroke();        // 枠を描画
context.fill();          // 塗りつぶし
</script>

上段左から、細い枠、太い枠、太い破線の枠(太さの指定が引き継がれています)

下段左から、塗りつぶし、塗りつぶしと枠、枠と塗りつぶし(左とは順序が逆)です。

表示例



SVG には、円を描く circle や、楕円を描く ellipse があるので、作成してみます。

(1) 円 (circle)

円を作成する際に使用します。(Canvas のメソッドではありません。)

circle(x, y, r)

円を指定する

引数 x円の中心の X座標
y円の中心の Y座標
r円の半径
戻り値なし
記述例
<canvas id="c" width="500" height="150"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');

function circle(x, y, r) {
  context.beginPath();
  context.arc(x, y, r, 0, Math.PI*2);
}

context.strokeStyle = "blue";
context.fillStyle = "yellow";

circle(40, 40, 30);
context.stroke();
circle(40, 110, 30);
context.fill();

context.lineWidth = 5;
circle(110, 40, 30);
context.stroke();
circle(110, 110, 30);
context.fill();
context.stroke();

context.setLineDash([10, 4]);              // 破線
circle(180, 40, 30);
context.stroke();
context.setLineDash([]);                   // 実線
circle(180, 110, 30);
context.stroke();
context.fill();
</script>

上段左から、細い枠、太い枠、太い破線の枠(太さの指定が引き継がれています)

下段左から、塗りつぶし、塗りつぶしと枠、枠と塗りつぶし(左とは順序が逆)です。

表示例

(2) 楕円 (ellipse)

楕円を作成する際に使用します。(Canvas のメソッドではありません。)

ellipse(x, y, rx, ry)

楕円を指定する

引数 x楕円の中心の X座標
y楕円の中心の Y座標
rx水平方向の半径
ry垂直方向の半径
戻り値なし
記述例
<canvas id="c" width="500" height="150"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');

function ellipse(x, y, rx, ry) {
  context.save();
  context.beginPath();
  context.translate(x, y);
  context.scale(rx/ry, 1);
  context.arc(0, 0, ry, 0, Math.PI*2);
  context.restore();
}

context.strokeStyle = "blue";
context.fillStyle = "yellow";

ellipse(70, 40, 60, 30);
context.stroke();
ellipse(70, 110, 60, 30);
context.fill();

context.lineWidth = 5;
ellipse(200, 40, 60, 30);
context.stroke();
ellipse(200, 110, 60, 30);
context.fill();
context.stroke();

context.setLineDash([10, 4]);              // 破線
ellipse(330, 40, 60, 30);
context.stroke();
context.setLineDash([]);                   // 実線
ellipse(330, 110, 60, 30);
context.stroke();
context.fill();
</script>

上段左から、細い枠、太い枠、太い破線の枠(太さの指定が引き継がれています)

下段左から、塗りつぶし、塗りつぶしと枠、枠と塗りつぶし(左とは順序が逆)です。

表示例

11.4.5  直線 (lineTo)

現在の描画位置から指定した位置に、直線を描くために使用します。

続けて使用すれば多角形を描くこともできます。

コンテキスト.lineTo(x, y)

直線の終点を指定する

引数 x直線の終点の X座標
y直線の終点の Y座標
戻り値なし
記述例
<canvas id="c" width="500" height="120"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');
context.strokeStyle = "blue";
context.beginPath();
context.moveTo(30, 10);
context.lineTo(10, 30);
context.lineTo(110, 30);
context.lineTo(60, 50);
context.lineTo(60, 10);
context.stroke();              // 青い枠

context.fillStyle = "yellow";
context.beginPath();
context.moveTo(30, 60);
context.lineTo(10, 80);
context.lineTo(110, 80);
context.lineTo(60, 100);
context.lineTo(60, 60);
context.fill();                // 黄色い塗りつぶし

context.lineWidth = 5;
context.beginPath();
context.moveTo(150, 10);
context.lineTo(130, 30);
context.lineTo(230, 30);
context.lineTo(180, 50);
context.lineTo(180, 10);
context.stroke();              // 太さ 5 の青い枠

context.beginPath();
context.moveTo(150, 60);
context.lineTo(130, 80);
context.lineTo(230, 80);
context.lineTo(180, 100);
context.lineTo(180, 60);
context.fill();                // 黄色い塗りつぶし
context.stroke();              // 太さ 5 の青い枠

context.setLineDash([10, 4]);              // 破線
context.beginPath();
context.moveTo(270, 10);
context.lineTo(250, 30);
context.lineTo(350, 30);
context.lineTo(300, 50);
context.lineTo(300, 10);
context.stroke();              // 太さ 5 の青い点線の枠

context.setLineDash([]);                   // 実線
context.beginPath();
context.moveTo(270, 60);
context.lineTo(250, 80);
context.lineTo(350, 80);
context.lineTo(300, 100);
context.lineTo(300, 60);
context.stroke();              // 太さ 5 の青い実線の枠
context.fill();                // 黄色い塗りつぶし
</script>

上段左から、細い枠、太い枠、太い破線の枠(太さの指定が引き継がれています)

下段左から、塗りつぶし、塗りつぶしと枠、枠と塗りつぶし(左とは順序が逆)です。

表示例



SVG には、折線を描く polyline や、多角形を描く polygon があるので、作成してみます。

(1) 折線 (polyline)

折線を作成する際に使用します。(Canvas のメソッドではありません。)

polyline(points)

折線を指定する

引数 points折れ線の各頂点の座標(x, y)配列
戻り値なし
記述例
<canvas id="c" width="500" height="120"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');

function polyline(points) {
  if (points.length <= 1)
    return;
  context.beginPath();
  context.moveTo(points[0][0], points[0][1]);
  for (var i = 1 ; i < points.length ; i++) {
    context.lineTo(points[i][0], points[i][1]);
  }
}

context.strokeStyle = "blue";
polyline([[30,10], [10,30], [110,30], [60,50], [60,10]]);         // 青い枠
context.stroke();

context.fillStyle = "yellow";
polyline([[30,60], [10,80], [110,80], [60,100], [60,60]]);        // 黄色い塗りつぶし
context.fill();

context.lineWidth = 5;
polyline([[150,10], [130,30], [230,30], [180,50], [180,10]]);     // 太さ 5 の青い枠
context.stroke();

polyline([[150,60], [130,80], [230,80], [180,100], [180,60]]);
context.fill();                                                   // 黄色い塗りつぶし
context.stroke();                                                 // 太さ 5 の青い枠

context.setLineDash([10, 4]);  // 破線
polyline([[270,10], [250,30], [350,30], [300,50], [300,10]]);     // 太さ 5 の青い点線の枠
context.stroke();

context.setLineDash([]);       // 実線
polyline([[270,60], [250,80], [350,80], [300,100], [300,60]]);
context.stroke();                                                 // 太さ 5 の青い枠
context.fill();                                                   // 黄色い塗りつぶし
</script>

上段左から、細い枠、太い枠、太い破線の枠(太さの指定が引き継がれています)

下段左から、塗りつぶし、塗りつぶしと枠、枠と塗りつぶし(左とは順序が逆)です。

表示例

(2) 多角形 (polygon)

多角形を作成する際に使用します。(Canvas のメソッドではありません。)

polygon(points)

多角形を指定する

引数 points多角形の各頂点の座標(x, y)配列
戻り値なし
記述例
<canvas id="c" width="500" height="120"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');

function polygon(points) {
  if (points.length <= 1)
    return;
  context.beginPath();
  context.moveTo(points[0][0], points[0][1]);
  for (var i = 1 ; i < points.length ; i++) {
    context.lineTo(points[i][0], points[i][1]);
  }
  context.closePath();
}

context.strokeStyle = "blue";
polygon([[30,10], [10,30], [110,30], [60,50], [60,10]]);         // 青い枠
context.stroke();

context.fillStyle = "yellow";
polygon([[30,60], [10,80], [110,80], [60,100], [60,60]]);        // 黄色い塗りつぶし
context.fill();

context.lineWidth = 5;
polygon([[150,10], [130,30], [230,30], [180,50], [180,10]]);     // 太さ 5 の青い枠
context.stroke();

polygon([[150,60], [130,80], [230,80], [180,100], [180,60]]);
context.fill();                                                   // 黄色い塗りつぶし
context.stroke();                                                 // 太さ 5 の青い枠

context.setLineDash([10, 4]);  // 破線
polygon([[270,10], [250,30], [350,30], [300,50], [300,10]]);     // 太さ 5 の青い点線の枠
context.stroke();

context.setLineDash([]);       // 実線
polygon([[270,60], [250,80], [350,80], [300,100], [300,60]]);
context.stroke();                                                 // 太さ 5 の青い枠
context.fill();                                                   // 黄色い塗りつぶし
</script>

上段左から、細い枠、太い枠、太い破線の枠(太さの指定が引き継がれています)

下段左から、塗りつぶし、塗りつぶしと枠、枠と塗りつぶし(左とは順序が逆)です。

表示例

11.4.6  曲線 (arcTo)

現在の描画位置から指定された座標と半径から求まる曲線を描くために使用します。

コンテキスト.arcTo(x1, y1, x2, y2, r)

座標と半径から求まる曲線を指定する

引数 x1制御点1の X座標
y1制御点1の Y座標
x2制御点2の X座標
y2制御点2の Y座標
r半径
戻り値なし

現在の座標 (x0,y0) から制御点1 (x1,y1) への直線と制御点1 (x1,y1) から制御点2 (x2,y2) への直線に内接する半径 r の円の円周上の一部となる曲線を描きます。曲線の開始点と終了点は、それぞれの線と円との接点になります。

記述例
<canvas id="c" width="500" height="120"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');

function draw() {
  context.save();
  context.beginPath();
  context.moveTo(40, 10);
  context.arcTo(20, 10, 10, 30, 30);
  context.lineTo(110, 30);
  context.arcTo(60, 50, 60, 10, 10);
  context.arcTo(60, 10, 30, 10, 5);
  context.closePath();
  context.restore();
}

context.strokeStyle = "blue";
context.translate(0, 0);
draw();
context.stroke();              // 青い枠

context.fillStyle = "yellow";
context.translate(0, 50);
draw();
context.fill();                // 黄色い塗りつぶし

context.lineWidth = 5;
context.translate(120, -50);
draw();
context.stroke();              // 太さ 5 の青い枠

context.beginPath();
context.translate(0, 50);
draw();
context.fill();                     // 黄色い塗りつぶし
context.stroke();                   // 太さ 5 の青い枠

context.setLineDash([10, 4]);  // 破線
context.translate(120, -50);
draw();
context.stroke();              // 太さ 5 の青い点線の枠

context.setLineDash([]);       // 実線
context.translate(0, 50);
draw();
context.stroke();                   // 太さ 5 の青い枠
context.fill();                     // 黄色い塗りつぶし
</script>

上段左から、細い枠、太い枠、太い破線の枠(太さの指定が引き継がれています)

下段左から、塗りつぶし、塗りつぶしと枠、枠と塗りつぶし(左とは順序が逆)です。

表示例

11.4.7  二次ベジェ曲線 (quadraticCurveTo)

二次ベジェ曲線を描くために使用します。制御点 (cpx, cpy) を 1 つだけ必要とし、始点(現在の座標)側と終点 (x, y) 側両方の曲線の傾斜を定義します。

コンテキスト.quadraticCurveTo(cpx, cpy, x, y)

二次ベジェ曲線を指定する

引数 cpx制御点の X座標
cpy制御点の Y座標
x終点の X座標
y終点の Y座標
戻り値なし
記述例
<canvas id="c" width="400" height="180"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');

context.beginPath();
context.strokeStyle = "blue";
context.lineWidth = 3;
context.moveTo(50, 10);
context.quadraticCurveTo(100, 160, 150, 110);
context.quadraticCurveTo(200, 60, 250, 110);
context.stroke();
</script>

(50,10) から (100,160) を制御点にして (150,110) まで曲線を引いています。そのあと、(200,60) を次の制御点にして引き続き (150,110) から (250,110) まで曲線を引いています。

なお、グレイの破線や色の薄い図形などは理解の助けになるように別途描いています。

表示例

2次ベジェ曲線で描くとしても、適切な制御点を見つけるのは簡単ではありません。そこで簡易的な2つの方法で描いてみます。

  • ポイントを一つ置きに曲線の通る点と制御点にする
  • ポイントの中点を曲線の通る点とし、ポイントを制御点にする
ポイントX 座標Y 座標
19045
27530
34530
42045
54565
66575
74590
830105
945115
1075120
1190105
1211070
なお、グレイの線はポイントを直線で結んだ場合の図形です。

11.4.8  三次ベジェ曲線 (bezierCurveTo)

三次ベジェ曲線を描くために使用します。制御点(cpx1, cpy1)(cpx2, cpy2)を 2 つにして、始点(現在の座標)側と終点 (x, y) 側両方の曲線の傾斜を定義します。

コンテキスト.bezierCurveTo(cpx1, cpy1, cpx2, cpy2, x, y)

三次ベジェ曲線を指定する

引数 cpx1制御点1の X座標
cpy1制御点1の Y座標
cpx2制御点2の Y座標
cpy2制御点2の Y座標
x終点の X座標
y終点の Y座標
戻り値なし
記述例
<canvas id="c" width="400" height="180"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');

context.beginPath();
context.strokeStyle = "blue";
context.lineWidth = 3;
context.moveTo(50, 10);
context.bezierCurveTo(170, 60, 60, 160, 200, 160);
context.bezierCurveTo(340, 160, 350, 110, 250, 60);
context.stroke();
</script>

(50,10) から (170,60) と (60,160) を制御点にして (200,160) まで曲線を引いています。そのあと、(340,160) と (350,110) とで引き続き (200,160) から (250,60) まで曲線を引いています。

なお、グレイの破線や色の薄い図形などは理解の助けになるように別途描いています。

表示例

11.4.9  パス内確認 (isPointInPath)

指定された座標がパスで描画される図形の内側(境界も含む)にあるかどうかを調べる際に使用します。

コンテキスト.isPointInPath(x, y[, fillRule])

指定された座標がパスで描画される図形の内側(境界も含む)にあるかどうかを調べる

ただし、座標 (x, y) は変形の影響を受けません。あくまで Canvas の左上が (0, 0) です。

引数 x終点の X座標
y終点の Y座標
fillRule塗りつぶしルール
nonzero全面塗りつぶし(規定値)
evenodd塗り分け
戻り値true(図形内側)、false(図形外側)

図形の内側か外側かは、塗りつぶしルールによって変わります。

記述例
<canvas id="c" width="400" height="250"></canvas>

<script>
function draw(x, y, r, fillRule) {
  context.beginPath();
  context.strokeStyle = "gray";
  context.fillStyle = "yellow";
  context.arc(x, y, r, -Math.PI/3, Math.PI*5/3);
  context.arc(x+r, y, r, -Math.PI*2/3, Math.PI*4/3);
  context.stroke();
  context.fill(fillRule);
}
function check(px, py, r, fillRule, x, y) {
  context.fillStyle = "black";
  context.fillText(context.isPointInPath(px, py, fillRule), x, y);
}

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

draw(40, 40, 30, "evenodd");
check(5, 40, "evenodd", 40 + 70, 40 + 20);
draw(40, 120, 30, "evenodd");
check(30, 120, "evenodd", 40 + 70, 120 + 20);
draw(40, 200, 30, "evenodd");
check(55, 200, "evenodd", 40 + 70, 200 + 20);

draw(190, 40, 30, "nonzero");
check(155, 40, "nonzero", 190 + 70, 40 + 20);
draw(190, 120, 30, "nonzero");
check(180, 120, "nonzero", 190 + 70, 120 + 20);
draw(190, 200, 30, "nonzero");
check(205, 200, "nonzero", 190 + 70, 200 + 20);
</script>

×の部分を調べています。結果は true か false で表示されます。

×は理解の助けになるように別途描いています。

表示例

isPointInPath メソッドの座標は変形の影響を受けません。

記述例
<canvas id="c" width="400" height="80"></canvas>

<script>
function draw(px, py, w, h) {
  context.beginPath();
  context.rect(px, py, w, h);
  context.fillStyle = "yellow";
  context.fill();
  context.strokeStyle = "gray";
  context.stroke();
}
function check(px, py) {
  context.fillStyle = "black";
  context.fillText(context.isPointInPath(px, py, "evenodd"), 110, 40);
}

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

context.translate(100, 0);     // 水平方向に 100 移動
draw(0, 0, 100, 50);
check(40, 30);
</script>

isPointInPath メソッドの座標は変形の影響を受けず、Canvas の左上を (0, 0) とした (40, 30) の×の位置です。(×などは理解の助けになるように別途描いています)

矩形は translate メソッドで、座標を水平方向に 100 移動させ、(0, 0) から描画しています。つまり、Canvas の左上を (0, 0) とした (100, 0) の位置になります。

したがって、isPointInPath メソッドで調べようとしている座標は図形の外側ということになります。

表示例


参考:等高線図
参考:等高線図  立体等高線図  ワイヤーフレーム立体図  ポリゴン立体図  (別ウィンドウで開きます)

11.5 テキスト

11.5.1 描画 (strokeText、fillText)

テキストの輪郭を図形として作成します。

(1) テキストの枠を描画する (strokeText)

テキストの枠(輪郭のみで塗りつぶしません)を描画します。

コンテキスト.strokeText(text, x, y[, maxWidth])

テキストの枠を描画する際に使用する。

引数 text描画する文字列
xテキストを配置する x座標
yテキストを配置する Y座標
maxWidthテキストの描画領域の最大幅(この幅を超えないように表示される)
戻り値なし
記述例
<canvas id="c" width="400" height="80"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');

context.beginPath();
context.strokeStyle = "blue";
context.font = "24pt 'MS ゴシック'";
context.strokeText("漢Mxhy", 10, 50);

context.strokeText("漢Mxhy", 200, 50, 30);       // 幅 30
context.stroke();
</script>

破線の交点がテキストを表示している座標です。また、右側は描画領域の幅を指定していますので、その幅の範囲で描画されています。

表示例

(2) 塗りつぶしテキストを描画する (fillText)

テキストを塗りつぶして描画します。

コンテキスト.fillText(text, x, y[, maxWidth])

テキストを塗りつぶして描画する際に使用する。

引数 text描画する文字列
xテキストを配置する x座標
yテキストを配置する Y座標
maxWidthテキストの描画領域の最大幅(この幅を超えないように表示される)
戻り値なし
記述例
<canvas id="c" width="400" height="80"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');

context.beginPath();
context.fillStyle = "blue";
context.font = "24pt 'MS ゴシック'";
context.fillText("漢Mxhy", 10, 50);

context.fillText("漢Mxhy", 200, 50, 30);       // 幅 30
context.fill();
</script>

破線の交点がテキストを表示している座標です。また、右側は描画領域の幅を指定していますので、その幅の範囲で描画されています。

表示例

11.5.2 フォントスタイル (font)

フォントスタイルに関わる属性を指定します。CSS の font と同じように指定します。

font プロパティ

フォントスタイルに関わる属性を定義する。

プロパティ
fontフォントスタイル(CSS の font と同じように、属性値を空白区切りで組み合わせて指定する。ただし、行の高さは normal に固定されている。)
属性値説明必須
bold太く×
bolderより太く(現状は bold と同じ)
lighterより細く(現状は normal と同じ)
italicイタリック体(専用フォントがあればそのフォントで表示する。
なければ oblique と同じ)
×
oblique斜体(標準フォントを傾けて表示する)
small-capsスモールキャプス体(小文字ではなく大文字を小さく表示する)×
サイズフォントサイズ(単位付きの数値か % 付きの割合)×
(規定値:10px)
文字列フォント名(フォント名に空白が含まれる場合は ' ' で囲む)

詳細は、CSS の font を参照

記述例
<canvas id="c" width="500" height="150"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');
context.fillStyle = "black";
context.font = "bold 20pt 'MS P明朝'";
context.fillText("いろいろ修飾された文字列", 10, 30);
context.font = "italic 20pt 'MS P明朝'";
context.fillText("いろいろ修飾された文字列", 10, 80);
context.font = "italic bold 20pt 'MS Pゴシック'";
context.fillText("いろいろ修飾された文字列", 10, 130);

context.font = "caption";
context.fillText("いろいろ修飾された文字列", 10, 160);
context.font = "small-caption";
context.fillText("いろいろ修飾された文字列", 10, 175);
context.font = "icon";
context.fillText("いろいろ修飾された文字列", 10, 190);
context.font = "menu";
context.fillText("いろいろ修飾された文字列", 10, 205);
context.font = "message-box";
context.fillText("いろいろ修飾された文字列", 10, 220);
context.font = "status-bar";
context.fillText("いろいろ修飾された文字列", 10, 235);
</script>
表示例

11.5.3 配置 (textAlign)

設定された座標に表示する、テキストの水平方向の位置を指定します。

textAlign プロパティ

テキストの水平方向の位置を定義する。

プロパティ説明
textAlignstart開始位置揃え (規定値)
end終了位置揃え
left左揃え
right右揃え
center中央揃え
記述例
<canvas id="c" width="500" height="150"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');
context.fillStyle = "blue";
context.textAlign = "start";
context.fillText("芸術は長く、人生は短し", 200, 20);
context.textAlign = "end";
context.fillText("芸術は長く、人生は短し", 200, 50);
context.textAlign = "left";
context.fillText("芸術は長く、人生は短し", 200, 80);
context.textAlign = "right";
context.fillText("芸術は長く、人生は短し", 200, 110);
context.textAlign = "center";
context.fillText("芸術は長く、人生は短し", 200, 140);
context.fill();
</script>

start と left、end と right が同じ位置になっていますが、これは日本語が左から右に表記するからです。start と end は表示する文字列の開始位置と終了位置で、left と right は表示する文字列の左と右です。

表示例

11.5.4 ベースライン (textBaseline)

ベースラインの位置を指定する際に使用します。

textBaseline プロパティ

ベースラインの位置を定義する。

プロパティ説明
textAligntop上端揃え
hanginghanging基底線を利用する(インド系言語)
middlemiddle基底線を利用する
alphabeticalphabetic基底線を利用する(アルファベット等) (規定値)
ideographicideographic基底線を利用する(ひらがな、漢字、ハングル等)
bottom下端揃え

属性値はおおよそ次のような位置になります。なお、ブラウザやフォント(?)によっても多少異なります。

記述例
<canvas id="c" width="500" height="160"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');
context.font = "20pt 'MS 明朝'";
context.fillStyle = "blue";
context.textBaseline  = "top";
context.fillText("漢Mxhy:top", 0, 50);
context.textBaseline  = "hanging";
context.fillText("漢Mxhy:hanging", 250, 50);
context.textBaseline  = "middle";
context.fillText("漢Mxhy:middle", 0, 100);
context.textBaseline  = "alphabetic";
context.fillText("漢Mxhy:alphabetic", 250, 100);
context.textBaseline  = "ideographic";
context.fillText("漢Mxhy:ideographic", 0, 150);
context.textBaseline  = "bottom";
context.fillText("漢Mxhy:bottom", 250, 150);
</script>

なお、グレイの破線などは理解の助けになるように別途描いています。

表示例

hanging や ideographic はブラウザによって位置が異なっているようです。

11.5.5 描画幅 (measureText)

テキストの描画幅を測定する際に使用します。

コンテキスト.measureText(text)

現在のフォントでテキストを描画した場合の描画幅を取得する。

引数 text描画する文字列
戻り値TextMetrics オブジェクト(描画幅は width プロパティ)
記述例
<canvas id="c" width="500" height="160"></canvas>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');
var s = "漢Mxhyの描画幅は";
context.fillStyle = "blue";

context.font = "14pt 'MS ゴシック'";
var metrics = context.measureText(s);
context.fillText(s, 0, 20);
context.fillText(metrics.width, 200, 20);

context.font = "14pt 'MS Pゴシック'";
metrics = context.measureText(s);
context.fillText(s, 0, 50);
context.fillText(metrics.width, 200, 50);

context.font = "italic 14pt 'MS Pゴシック'";
metrics = context.measureText(s);
context.fillText(s, 0, 80);
context.fillText(metrics.width, 200, 80);

context.font = "bold 14pt 'MS Pゴシック'";
metrics = context.measureText(s);
context.fillText(s, 0, 110);
context.fillText(metrics.width, 200, 110);

context.font = "italic bold 14pt 'MS Pゴシック'";
metrics = context.measureText(s);
context.fillText(s, 0, 140);
context.fillText(metrics.width, 200, 140);

context.translate(350, 30);
context.rotate(Math.PI/6);
context.font = "14pt 'MS Pゴシック'";
metrics = context.measureText(s);
context.fillText(s, 0, 0);
context.fillText(metrics.width, 180, 0);
</script>

フォント名やフォントスタイルを変えて描画幅を取得しています。

右の例は、回転させて描画幅を取得していますが、回転させても幅は変わらないようです。

表示例

なお、古い では、TextMetrics オブジェクト の width プロパティが実数値のこともあるようです。




参考:グラフ
参考:円グラフ  積層グラフ  レーダーチャート   (別ウィンドウで開きます)

11.6 イメージ

11.6.1 描画 (drawImage)

イメージを描画する際に使用します。イメージの描画は現在のパスには影響を与えません。

コンテキスト.drawImage(image, [sx, sy, sw, sh, ]dx, dy[, dw, dh])

イメージを描画する際に使用する。

sx, sy, sw, sh が指定されていなければイメージ全体が、指定されていたらイメージ全体ではなく指定された部分のみが描画対象になる。

dw, dh が指定されていなければ、描画対象のイメージの幅と高さのまま、指定されていたらその幅や高さに拡縮されて描画される。

ただし、sx, sy, sw, sh が指定された場合、dw, dh を省略できない。

引数 image描画するイメージ(img 要素、canvas 要素、video 要素、Image オブジェクト)
sx切り取るイメージの X座標(規定値:0)
sy切り取るイメージの Y座標(規定値:0)
sw切り取るイメージの幅(規定値:イメージの幅)
sh切り取るイメージの高さ(規定値:イメージの高さ)
dxイメージを描画する領域の X座標
dyイメージを描画する領域の Y座標
dwイメージを描画する領域の幅(規定値:イメージの幅)
dhイメージを描画する領域の高さ(規定値:イメージの高さ)
戻り値なし

drawImage メソッドは、当然のことながら基になる img タグに画像が読み込まれていなければなりません。そこで、この例では確実に画像が読み込まれた後に drawImage メソッドが実行されるように、img タグに onLoad イベントハンドラを記述し、そこから呼び出されるようにしています。

記述例
<canvas id="c" width="500" height="120"></canvas>

<script>
function draw() {
  var canvas = document.getElementById('c');
  var context = canvas.getContext('2d');

  var img = document.getElementById('bear');
  context.drawImage(img, 10, 10);                             // そのままの大きさ
  context.drawImage(img, 100, 10, 30, 30);                    // 縮小表示
  context.drawImage(img, 23, 0, 50, 45, 200, 10, 100, 90);    // 1部分の拡大表示
}
</script>

<img id="bear" src="bear.png" width="74" height="74" style="display:none;" onLoad="draw()">
表示例

11.6.2 ImageData オブジェクトの取得と設定 (getImageData、putImageData)

ImageData オブジェクトの取得や設定をする際に使用します。

(1) ImageData オブジェクトの取得 (getImageData)

指定範囲の ImageData オブジェクトを Canvas から取得する際に使用します。

コンテキスト.getImageData(sx, sy, sw, sh)

ImageData オブジェクトを Canvas から取得する。

引数 sx取得するイメージの X座標
sy取得するイメージの Y座標
sw取得するイメージの幅
sh取得するイメージの高さ
戻り値ImageData オブジェクト(主なプロパティは以下の通り)
data取得したイメージを含んだ RGBA 順の 1 次元配列(それぞれの値は 0 ~ 255)
height取得したイメージの高さ
width取得したイメージの幅

(2) ImageData オブジェクトの設定 (putImageData)

ImageData オブジェクトを Canvas に書き戻す際に使用します。

コンテキスト.putImageData(imagedata, dx, dy[, dirtyX, dirtyY, dirtyWidth, dirtyHeight])

ImageData オブジェクトを Canvas に書き戻す。

引数 imagedata描画する ImageData オブジェクト
dxイメージを描画する領域の X座標
dyイメージを描画する領域の Y座標
dirtyX書き戻す範囲の X座標(規定値:0)
dirtyY書き戻す範囲の Y座標(規定値:0)
dirtyWidth書き戻す範囲の幅(規定値:ImageData オブジェクトが持つイメージの幅)
dirtyHeight書き戻す範囲の高さ(規定値:ImageData オブジェクトが持つイメージの高さ)
戻り値なし
記述例
<canvas id="s" width="80" height="80"></canvas>
<canvas id="d" width="500" height="80"></canvas>

<script>
function draw() {
  var s = document.getElementById('s');
  var sc = s.getContext('2d');
  var d = document.getElementById('d');
  var dc = s.getContext('2d');

  var img = document.getElementById("bear");
  sc.drawImage(img, 0, 0);
  var imageData = sc.getImageData(0, 0, 100, 200);
  dc.putImageData(imageData, 0, 0);                      // 全体
  dc.putImageData(imageData, 80, 0, 0, 0, 37, 37);       // 左上
  dc.putImageData(imageData, 80, 0, 38, 38, 74, 74);     // 右下
}
</script>

<img id="bear" src="bear.png" width="74" height="74" style="display:none;" onLoad="draw()">

緑色の背景の Canvas から うすい黄色の Canvas にイメージを移しています。

一つ目は全身、二つ目は左上だけ、三つ目は右下だけです。

表示例

上の例では、getImageData と putImageData は別々の Canvas に対して操作していますが、同じ Canvas でも構いません。

記述例
<canvas id="c" width="80" height="80"></canvas>
<button class="switch" onclick="gray()">グレイスケール</button>
<button class="switch" onclick="draw()">元に戻す</button>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');

function draw() {
  var img = document.getElementById('bear');
  context.drawImage(img, 0, 0);
}

function gray()
{
  var imagedata = context.getImageData(0, 0, 74, 74);
  var data = imagedata.data;       // ピクセルデータを data にセット
  var pix = data.length / 4;       // ピクセル数を取得
  for (var i = 0 ; i < pix ; i++) {
    // 赤・緑・青のデータを取得
    var r = data[i*4];
    var g = data[i*4+1];
    var b = data[i*4+2];

    var gr = parseInt((r * 30 + g * 59 + b * 11) / 100);    // グレイスケール化する処理

    // グレイスケール化したデータを再セット
    data[i*4] = gr;
    data[i*4+1] = gr;
    data[i*4+2] = gr;
  }
  context.putImageData(imagedata, 0, 0);           // 変更したピクセルデータを書き戻す
}
</script>

<img id="bear" src="bear.png" width="74" height="74" style="display:none;" onLoad="draw()">
表示例

11.6.3 ImageData オブジェクトの生成 (createImageData)

ImageData オブジェクトの生成をする際に使用します。

コンテキスト.createImageData(sw, sh)

ImageData オブジェクトを生成する。生成されたオブジェクトにあるすべてのピクセルは、透明な黒(rgba(0, 0, 0, 0))となる。

引数 sw生成するイメージの幅
sh生成するイメージの高さ
戻り値ImageData オブジェクト(主なプロパティは以下の通り)
data生成したイメージを含んだ RGBA 順の 1 次元配列(それぞれの値は 0 ~ 255)
height生成したイメージの高さ
width生成したイメージの幅

コンテキスト.createImageData(imagedata)

ImageData オブジェクトを生成する。生成されたオブジェクトにあるすべてのピクセルは、透明な黒(rgba(0, 0, 0, 0))となる。

引数 imagedataこのオブジェクトに含まれるイメージの幅と高さで生成する
戻り値ImageData オブジェクト(主なプロパティは以下の通り)
data生成したイメージを含んだ RGBA 順の 1 次元配列(それぞれの値は 0 ~ 255)
height生成したイメージの高さ
width生成したイメージの幅
記述例
<canvas id="c" width="500" height="120"></canvas>
<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');

var imagedata = context.createImageData(canvas.width, canvas.height);   // 空のスレートを生成
var data = imagedata.data;
var width = imagedata.width;
var height = imagedata.height; // ImageDataの幅と高さを定義

for (var y = 0; y < height; ++y) {
  for (var x = 0; x < width; ++x) {
    var base = (x+y*width)*4;
    data[base+0] = 255*x/width;
    data[base+1] = 255*y/height;
    data[base+2] = Math.max(255-x-y,0);
    data[base+3] = 255;
  }
}  
context.putImageData(imagedata, 0, 0);
</script>
表示例



参考:時計
参考:ミッキー時計   (別ウィンドウで開きます)

11.7 グラデーション

グラデーションは塗り潰しに用いる色を徐々に変化させることで、単色によるものに比べて滑らかな見た目をもたらします。

Canvas においてもグラデーションを線形に掛ける createLinearGradient メソッドと円形に掛ける createRadialGradient メソッドが提供されています。

また、実際にグラデーションを始めるたり終わらせたりする位置や色は、addColorStop メソッドで指定します。

11.7.1 線形グラデーション (createLinearGradient)

座標 (x1,y1) から座標 (x2,y2) の範囲に線形のグラデーションを描画します。

座標の (0,0) は Canvas の左上です。描画する図形の左上ではありません。

また、変形によって座標軸が移動したような場合は座標軸に合わせてグラデーションも変形します。

コンテキスト.createLinearGradient(x1, y1, x2, y2)

座標 (x1,y1) から座標 (x2,y2) の範囲に線形のグラデーションを描画する際に使用する。

引数 x1グラデーションの開始地点の X座標
y1グラデーションの開始地点の Y座標
x2グラデーションの終了地点の X座標
y2グラデーションの終了地点の Y座標
戻り値なし

グラデーションは、開始地点 (x1,y1) から終了地点 (x2,y2) に向かって行われます。x1 と x2 が等しいときは縦向きのグラデーション、y1 と y2 が等しいときは横向きのグラデーション、それ以外は斜めのグラデーションになります。

記述例
<canvas id="c" width="500" height="120"></canvas>
<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');

var grad =context.createLinearGradient(0, 0, 0, 100);
grad.addColorStop(0,'green');    // 緑色
grad.addColorStop(1,'azure');    // 水色
context.fillStyle = grad;
context.rect(0, 0, 100, 100);
context.fill();

context.beginPath();
grad =context.createLinearGradient(120, 0, 220, 0);
grad.addColorStop(0,'green');    // 緑色
grad.addColorStop(1,'azure');    // 水色
context.fillStyle = "gray";
context.rect(120, 0, 100, 100);
context.fill();

context.beginPath();
grad =context.createLinearGradient(240, 0, 340, 100);
grad.addColorStop(0,'green');    // 緑色
grad.addColorStop(1,'azure');    // 水色
context.fillStyle = "gray";
context.rect(240, 0, 100, 100);
context.fill();
</script>

グレイの線はグラデーションの方向を示すために別途描いています。

表示例

変形を行っても座標軸に対するグラデーションの方向は変わりません。この例では X 軸方向のグラデーションを指定しています。

記述例
<canvas id="c" width="500" height="120"></canvas>
<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');

var grad =context.createLinearGradient(10, 0, 110, 0);
grad.addColorStop(0,'green');    // 緑色
grad.addColorStop(1,'azure');    // 水色
context.fillStyle = grad;

context.translate(10, 10);
context.fillRect(10, 10, 100, 50);

context.translate(160, 90);
context.rotate(-60*Math.PI/180);
context.fillRect(10, 10, 100, 50);

context.setTransform(1, Math.tan(Math.PI/6), 0, 1, 320, 10);    
context.fillRect(10, 10, 100, 50);
</script>

X 軸方向のグラデーションです。右2つの図形は回転や傾斜によって X 軸の向きを変えていますが、グラデーションの方向もそれに合わせて変わっています。

グレイの線は別途描いた座標軸です。

表示例

上の例は、グラデーションの開始位置と幅・高さを図形と合わせていますので、図形ごとに図形いっぱいにグラデーションが行われいます。

グラデーションの幅・高さより図形の幅・高さが小さければ、グラデーションの一部を切り取る形で塗りつぶすことになります。

記述例
<canvas id="c" width="500" height="120"></canvas>
<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');

var grad =context.createLinearGradient(0, 0, 200, 0);
grad.addColorStop(0,'green');    // 緑色
grad.addColorStop(1,'azure');    // 水色
context.fillStyle = grad;

context.rect(10, 30, 80, 40);
context.fill();

context.rect(100, 30, 80, 40);
context.fill();
</script>

左の2つの図形はグラデーションの一部を切り取った形で塗りつぶされています。グレイの線がグラデーションの幅を示しています。

右の図はグラデーションのイメージと切り取られた部分を表しています。

表示例


11.7.2 円形グラデーション (createRadialGradient)

中心座標(x1,y1)、半径 r1 から中心座標(x2,y2)、半径 r2 の範囲に円形のグラデーションを描画します。

座標の (0,0) は Canvas の左上です。描画する図形の左上ではありません。

コンテキスト.createRadialGradient(x1, y1, r1, x2, y2, r2)

開始円(中心座標(x1,y1)、半径 r1)から終了円(中心座標(x2,y2)、半径 r2)の範囲に円形のグラデーションを描画する際に使用する。

ただし、開始円は、終了円の中にある必要があります。

引数 x1グラデーションの開始円の X座標
y1グラデーションの開始円の Y座標
r1グラデーションの開始円の半径
x2グラデーションの終了円の X座標
y2グラデーションの終了円の Y座標
r2グラデーションの終了円の半径
戻り値なし

グラデーションは、開始円から終了円に向かって行われます。

記述例
<canvas id="c" width="500" height="120"></canvas>
<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');

var grad =context.createRadialGradient(50, 50, 0, 50, 50, 50);
grad.addColorStop(0,'green');    // 緑色
grad.addColorStop(1,'azure');    // 水色
context.fillStyle = "gray";
context.rect(0, 0, 100, 100);
context.fill();

context.beginPath();
grad =context.createRadialGradient(140, 50, 10, 170, 50, 50);
grad.addColorStop(0,'green');    // 緑色
grad.addColorStop(1,'azure');    // 水色
context.fillStyle = grad;
context.rect(120, 0, 100, 100);
context.fill();

context.beginPath();
grad =context.createRadialGradient(280, 40, 20, 300, 60, 50);
grad.addColorStop(0,'green');    // 緑色
grad.addColorStop(1,'azure');    // 水色
context.fillStyle = grad;
context.rect(240, 0, 100, 100);
context.fill();
</script>

グレイの円はグラデーションの開始円と終了円を示すように別途描いています。開始円は終了円の中に含まれている必要があります。

なお、開始円の内側と終了円の外側はグラデーションではなく単色になります。

表示例


変形を行っても座標軸に対するグラデーションの方向は変わりません。

記述例
<canvas id="c" width="500" height="120"></canvas>
<script>
function draw() {
  context.save();
  context.beginPath();
  context.arc(60, 60, 50, 0, Math.PI*2);
  context.fill();
  context.restore();
}

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

var grad =context.createRadialGradient(30, 60, 10, 60, 60, 50);
grad.addColorStop(0,'green');    // 緑色
grad.addColorStop(1,'azure');    // 水色
context.fillStyle = grad;

context.translate(10, 10);
draw();

context.translate(160, 90);
context.rotate(-60*Math.PI/180);
draw();

context.setTransform(1, Math.tan(Math.PI / 6), 0, 1, 340, 10);    
draw();
</script>

右2つの図形は回転や傾斜によって X 軸の向きを変えていますが、グラデーションの方向もそれに合わせて変わっています。

グレイの線は別途描いた座標軸です。

表示例

上の例は、グラデーションの開始位置と幅・高さを図形と合わせていますので、図形ごとに図形いっぱいにグラデーションが行われいます。

グラデーションの幅・高さより図形の幅・高さが小さければ、グラデーションの一部を切り取る形で塗りつぶすことになります。

記述例
<canvas id="c" width="500" height="120"></canvas>
<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');

var grad =context.createRadialGradient(100, 100, 50, 100, 100, 100);
grad.addColorStop(0,'green');    // 緑色
grad.addColorStop(1,'azure');    // 水色
context.fillStyle = grad;

context.strokeStyle = "gray";

context.beginPath();
context.moveTo(100, 100);
context.arc(100, 100, 100, Math.PI*5/4, Math.PI*7/4);
context.closePath();
context.fill();

context.beginPath();
context.arc(60, 140, 30, 0, Math.PI*2);
context.fillRect(50, 115, 100, 50);
</script>

左の2つの図形はグラデーションの一部を切り取った形で塗りつぶされています。グレイの線がグラデーションの幅を示しています。

右の図はグラデーションのイメージと切り取られた部分を表しています。

表示例

11.7.3 色傾斜 (addColorStop)

stop 要素は、createLinearGradient メソッドや createRadialGradient メソッドなどで定義された勾配ベクトルに基準となる色の位置を指定します。addColorStop 要素間の色は線形に補間されます。なお、addColorStop メソッドで設定された範囲外は通常単色で塗りつぶされます。

0 がグラデーションの開始位置で、1 が終了位置です。

コンテキスト.addColorStop(offset, color)

グラデーションに使用する色とその色に変わる位置を指定する。

引数 offset0 ~ 1(色が変わる位置の、グラデーションの開始位置からの割合)
colorグラデーションの色
次の値は代表的な指定方法です。詳しくは、「1.2.1 色」 を参照してください。
説明
#rrggbb赤緑青、各色16進数2ケタ
カラーネーム代表的ない色に付けられた名称(Web カラー一覧 参照)
rgb(rrr, ggg, bbb)赤緑青、各色10進数
戻り値なし
記述例
<canvas id="c" width="400" height="200"></canvas>
<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');
context.textAlign = "center";

context.save();
var grad =context.createLinearGradient(0, 0, 300, 0);
grad.addColorStop(0.2,'blue');    // 0.2 より左は blue 単色
grad.addColorStop(0.5,'green');
grad.addColorStop(0.8,'yellow');  // 0.8 より右は yellow 単色
context.fillStyle = grad;
context.fillRect(0, 0, 300, 80);

context.beginPath();
context.translate(0, 100);
context.scale(1, 80/300);
grad = context.createRadialGradient(150, 150, 0, 150, 150, 150);
grad.addColorStop(0.2,'blue');    // 0.2 より左は blue 単色
grad.addColorStop(0.5,'green');
grad.addColorStop(0.8,'yellow');  // 0.8 より右は yellow 単色
context.fillStyle = grad;
context.fillRect(0, 0, 300, 300);
context.restore();
</script>

0.2 ~ 0.8 が勾配ベクトルとなります。

0 ~ 0.2 は 青単色、0.8 ~ 1 は 黄単色です。その間は、0.2 ~ 0.5 は、青と緑の、0.5 ~ 0.8 は、緑と黄のグラデーションになります。

なお、"勾配ベクトル"とその下のグレイの線などは理解の助けになるように別途描いています。

表示例


また、offset が同じ stop 要素があった場合は、そこでグラデーションは終了し左右が別のグラデーションになります。

記述例
<canvas id="c" width="500" height="120"></canvas>
<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');
context.textAlign = "center";

context.save();
var grad =context.createLinearGradient(0, 0, 300, 0);
grad.addColorStop(0.2,'yellow');    // 0.2 より左は yellow 単色
grad.addColorStop(0.5,'blue');      // 0.5 で blue と green に分かれる
grad.addColorStop(0.5,'green');
grad.addColorStop(0.8,'yellow');    // 0.8 より右は yellow 単色
context.fillStyle = grad;
context.fillRect(0, 0, 300, 80);

context.beginPath();
context.translate(350, 0);
context.scale(1, 80/300);
grad = context.createRadialGradient(150, 150, 0, 150, 150, 150);
grad.addColorStop(0.2,'yellow');    // 0.2 より左は yellow 単色
grad.addColorStop(0.5,'blue');      // 0.5 で blue と green に分かれる
grad.addColorStop(0.5,'green');
grad.addColorStop(0.8,'yellow');    // 0.8 より右は yellow 単色
context.fillStyle = grad;
context.fillRect(0, 0, 300, 300);
context.restore();
</script>

offset が 0.5 の addColorStop メソッドが2つあるので、そこで左右が別のグラデーションになります。

なお、"勾配ベクトル"とその下のグレイの線などは理解の助けになるように別途描いています。

表示例

11.8 パターン (createPattern)

背景パターンとその繰り返し方法を指定する際に使用します。

背景パターンの開始位置は、canvas 要素の左上です。描画する図形の左上ではありませんので注意してください。

コンテキスト.createPattern(image, repetition)

背景パターンとその繰り返し方法を指定する。

引数 image描画するイメージ(img 要素、canvas 要素、video 要素、Image オブジェクト)
repetition繰り返し方法
説明
repeat水平・垂直の両方向に背景パターンを繰り返す
repeat-x水平方向にのみ背景パターンを繰り返す
repeat-y垂直方向にのみ背景パターンを繰り返す
no-repeat背景パターンを繰り返さない
戻り値CanvasPattern オブジェクト

矩形をパターンで敷き詰めることをします。敷き詰めるパターンは です。

記述例
<canvas id="c1" width="120" height="100"></canvas>
<!-- 以下略 -->

<canvas id="p" width="20" height="20" style="display:none;"></canvas>    <!-- パターン用 -->
<script>
function draw(id, repeat) {
  var canvas = document.getElementById(id);
  var context = canvas.getContext('2d');
  context.strokeStyle = "gray";
  context.fillStyle = context.createPattern(pattern, repeat);
  context.beginPath();
  context.rect(10, 10, 80, 60);
  context.fill();
  context.stroke();
}
var pattern = document.getElementById('p');
var context = pattern.getContext('2d');
context.fillStyle = "orange";
context.arc(10, 10, 10, 0, Math.PI*2);
context.fill();      // パターンの作成

draw("c1", "no-repeat");
draw("c2", "repeat-y");
draw("c3", "repeat-y");
draw("c4", "repeat");
</script>

背景パターンの開始位置は、canvas 要素の左上です(描画する図形の左上ではありません)。

したがって、no-repeat では canvas の左上、repeat-x では canvas の上一列、repeat-y では canvas の左一列しか表示されません。

外側の薄いグレイの矩形は、Canvas を表しています。色の薄い背景はそこにどのように背景パターンが繰り返されるかを表しています。内側のグレイの矩形は描画した図形です。実際にはこの描画した図形の範囲内だけ背景パターンが描かれます。

なお、色の薄い背景やグレイの矩形などは、理解の助けになるように別途描いています。

表示例

パターンを変形させることもできます。

記述例
<canvas id="c1" width="120" height="100"></canvas>
<!-- 以下略 -->

<canvas id="p" width="20" height="20" style="display:none;"></canvas>    <!-- パターン用 -->

<script>
function draw(id, repeat) {
  var canvas = document.getElementById(id);
  var context = canvas.getContext('2d');
  context.strokeStyle = "gray";
  context.fillStyle = context.createPattern(pattern, repeat);
  context.beginPath();
  context.rect(30, 30, 80, 60);
  context.fill();
  context.stroke();
}
function makePattern(context, rad) {
  context.fillStyle = "orange";
  context.beginPath();
  for (var i = -1 ; i < 1 ; i++) {
    for (var j = -1 ; j < 2 ; j++) {
      context.beginPath();
      context.arc(rad * 2 * i + rad, rad * 2 * j + rad, rad, 0, Math.PI*2);
      context.fill();
    }
  }
}

var pattern = document.getElementById('p');
var context = pattern.getContext('2d');
var sx = 0.5;
var sy = 1;
pattern.width = 20*sx;
pattern.height = 20*sy;
context.scale(sx, sy);
makePattern(context, 10);
draw("c1", "repeat");

var a = -45*Math.PI/180;
var w = Math.abs(Math.cos(a));
var h = Math.abs(Math.sin(a));
pattern.width = 20*w*2;
pattern.height = 20*h*2;
context.rotate(a);
makePattern(context, 10);
draw("c2", "repeat");

pattern.width = 20*w*2*sx;
pattern.height = 20*h*2*sy;
context.translate(pattern.width/2, pattern.height/2);
context.scale(sx, sy);
context.rotate(a);
makePattern(context, 10);
draw("c3", "repeat");
</script>

左上のグレイの矩形が1つのパターンを表しています。このパターンが繰り返し表示されています。

なお、色の薄い背景やグレイの矩形などは、理解の助けになるように別途描いています。

表示例

11.9 クリッピング (clip)

切り抜き指定した領域と、その後にパスで描かれた領域の重なる部分だけが切り抜き表示されます。

切り抜き領域が算出される際には、開いているサブパスも暗黙的に閉じられて切り抜きが適用されますが、 実際にサブパスが閉じられるわけではありません。

パスで切り抜き(クリッピング)する際に使用します。

クリッピングは、図形だけでなく画像やテキストでも行われます。

コンテキスト.clip([fillRule])

パスで切り抜き(クリッピング)する際に使用する。

引数 fillRule塗りつぶしルール
nonzero全面塗りつぶし(規定値)
evenodd塗り分け
戻り値なし
記述例
<canvas id="c" width="500" height="120"></canvas>
<script>
function clipArea(x, y, r, fillRule) {
  context.beginPath();
  context.arc(x, y, r, -Math.PI/3, Math.PI/3);
  context.arc(x, y, r, Math.PI/3, -Math.PI/3);
  context.arc(x+r, y, r, -Math.PI*4/6, Math.PI*4/6);
  context.arc(x+r, y, r, Math.PI*4/6, -Math.PI*4/6);
  context.clip(fillRule);
}

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

var grad =context.createLinearGradient(0, 0, 100, 0);
grad.addColorStop(0.2,'blue');      // 0.2 より左は blue 単色
grad.addColorStop(0.5,'green');
grad.addColorStop(0.8,'yellow');    // 0.8 より右は yellow 単色
context.fillStyle = grad;

context.save();
clipArea(40, 40, 30, "evenodd");
context.fillRect(10, 10, 100, 80);
context.restore();

context.translate(150, 0);
clipArea(40, 40, 30, "nonzero");
context.fillRect(10, 10, 100, 80);
</script>

左の図形は evenodd で、右が nonzero です。クリッピングの形式を変更しています。

なお、クリップエリアの解除はできないようです。クリッピングを指定する前の状態を save しておき、解除したいところで restore します。

表示例

11.10 合成 (globalCompositeOperation)

合成処理を変更する際に使用します。

それまでに描画された図形などすべてに対して、それ以降に描画する図形などをどのように合成するかを指定します。

globalCompositeOperation プロパティ

図形やイメージの合成方法を指定する。

プロパティ説明
globalCompositeOperationsource-atop重なった部分は新イメージ、それ以外は元イメージのみが表示される
source-in重なった部分は新イメージが表示され、それ以外は表示されない
source-out新イメージのみの部分が表示される
source-over重なった部分は新イメージ、それ以外はそれぞれのイメージが表示される (規定値)
destination-atop重なった部分は元イメージ、それ以外は新イメージのみが表示される
destination-in重なった部分は元イメージが表示され、それ以外は表示されない
destination-out元イメージのみの部分が表示される
destination-over重なった部分は元イメージ、それ以外はそれぞれのイメージが表示される
lighter重なった部分は混色され、それ以外はそれぞれのイメージが表示される
copy新イメージが表示される
xor重なった部分は表示されず、それ以外はそれぞれのイメージが表示される

記述例
<canvas id="c00" width="70" height="70"></canvas><!-- 途中略 --><canvas id="c03" width="70" height="70"></canvas>
<!-- 以下略 -->

<script>
var oprtns = [
  ["source-atop","source-in","source-out","source-over"],
  ["destination-atop","destination-in","destination-out","destination-over"],
  ["lighter","copy","xor",""]
];
function square(x, y) {
  context.beginPath();
  context.fillStyle = "blue";
  context.fillRect(x, y, 40, 40);
}
function circle(x, y) {
  context.beginPath();
  context.fillStyle = "red";
  context.arc(x + 30, y + 30, 20, 0, Math.PI*2);
  context.fill();
}
function draw(x, y, composite) {
  square(x, y);
  context.globalCompositeOperation = composite;
  circle(x, y);
}

var canvas;
var context;
for (var i = 0 ; i < 3 ; i++) {
  for (var j = 0 ; j < 4 ; j++) {
    canvas = document.getElementById('c' + i + j);
    context = canvas.getContext('2d');
    if (oprtns[i][j] != "") {
      draw(10, 10, oprtns[i][j]);
    }
  }
}
</script>

青の矩形の後に赤の円を描いています。globalCompositeOperation によって合成方法が変わります。

グレイの枠は理解の助けになるように別途描いています。

表示例

11.11 アニメーション

Canvas には、アニメーションに関するメソッドはありません。Canvas は 1度描いたグラフィックスは動かせません。そのため、描いた図形を全部消し、また描いて全部消し...を繰り返すなどして、アニメーションを実現します。

繰り返しは、主に window.requestAnimationFrame を使用します。

記述例
<canvas id="c" width="200" height="200"></canvas>
<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');
var requestId;

function draw() {
  requestId = window.requestAnimationFrame(draw);

  context.clearRect(0, 0, 200, 200);
  context.globalAlpha = 1;
  context.save();
  var sec = (new Date()).getSeconds();
  var r = sec % 12;
  context.globalAlpha = 0.6;
  context.beginPath();
  context.moveTo(100, 100);
  context.arc(100, 100, 120, Math.PI*r/6, Math.PI*(r+1)/6);
  context.closePath();
  context.clip();
  context.drawImage(img, 0, 0);
  context.fill();
  context.restore();
}

var img = document.getElementById('map');
var grad = context.createRadialGradient(100, 100, 0, 100, 100, 90);
grad.addColorStop(0,'green');    // 緑色
grad.addColorStop(1,'azure');    // 水色
context.fillStyle = grad;

requestId = window.requestAnimationFrame(draw);
</script>

<img id="map" src="Nishinoshima.png" width="200" height="200" style="display:none;">

アニメーションは回転する扇形の部分です。背景の薄い色の画像は別途描いています。

表示例



参考:回転する正十二面体
参考:回転する正十二面体 (別ウィンドウで開きます)

11.12 画像出力 (toBlob)

キャンバスに含まれる画像を表す Blob オブジェクトを生成します。Blob (Binary Large Object)とは、一般的に画像や音声などの大きなバイナリデータそのまま格納するためのデータ型です。

コンテキスト.toBlob(関数[, MIME[, 画質]])

キャンバスに含まれる画像を表す Blob オブジェクトを非同期で生成する。非同期なので Blob が生成される前に次の命令が実行される。

Blob が生成されたら、第一引数の関数が呼ばれる。

引数 関数Blob オブジェクトを受け取るコールバック関数
関数の形式
function(blob)
 blob:   Blob オブジェクト
MIME画像のMIMEタイプ(image/???)  (規定値:image/png)   参照:MIME タイプ
画質画質(jpeg か webp のとき、0~1)  (規定値:0.92)
戻り値なし

「スナップショット」ボタンをクリックしてください。そのときの canvas 内の画像が img 要素に表示されます。

記述例
<canvas id="c" style="background-color: black;"></canvas>
<img id="img"><br>
<button class="switch" onclick="snapshot()">スナップショット</button>

<script>
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');

// 一部略 


function snapshot() {
  canvas.toBlob(function(blob) {img.src = URL.createObjectURL(blob);});
}
</script>
表示例



参考:迷路

迷路から地上へ脱出してください。下のリンクから実行できます。

 左はイメージ画像です。
 
参考:迷路 (別ウィンドウで開きます)