canvas 要素
canvas 要素の描画領域を定義する。HTML のタグとして記述します。
属性
属性名 | 属性値 | 説明 | 必須 |
---|---|---|---|
width | 1 ~ | 描画領域の幅 (規定値:300) | × |
height | 1 ~ | 描画領域の高さ (規定値:150) | × |
canvas 要素は、WEBブラウザ上で動的にグラフィックを描画するための仕組みです。もともと Apple社が Safariの独自拡張として策定したものでしたが、現在はほとんどのブラウザ上で canvas 要素が利用できるようになっています。
Canvas では、HTML と JavaScript を組み合わせて描画内容を指定します。 Canvas による描画は、大まかに以下のような流れとなります。
canvas 要素の描画領域を定義する。HTML のタグとして記述します。
属性名 | 属性値 | 説明 | 必須 |
---|---|---|---|
width | 1 ~ | 描画領域の幅 (規定値:300) | × |
height | 1 ~ | 描画領域の高さ (規定値:150) | × |
なお、描画領域の幅と高さは後からでも変更・参照することができます。
canvas 要素のオブジェクトの持つ描画領域の幅または高さを定義・参照する。
プロパティ | 値 | 説明 |
---|---|---|
width | 1 ~ | 描画領域の幅 |
height | 1 ~ | 描画領域の高さ |
<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 | コンテキストオブジェクトの種類 "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>
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 | |
---|---|---|
描画形式 | ラスター(ビットマップ)形式(拡大するとギザギザが目立つ) | ベクター形式 |
描画方式 | canvas 要素で描画領域(キャンバス)を確保し、JavaScriptを用いて描画する | 図形一つひとつが svg 要素の子要素として記載される |
描画基本単位 | 直線や曲線などの図形の構成部分 | 円や矩形などの図形 |
イベント | どの図形に対するイベントかを判定する必要がある | 個々の図形のタグに onclick のように記述できる |
スタイルシート指定 | 不可 | 可 |
利用性 | png、jpeg などのファイル形式で保存できる | 拡張子 svg として保存するとイメージファイルとして img 要素の src にも記述できる |
パフォーマンス | 小さい多数の図形の描画に向く | 大きい少数の図形の描画に向く |
アニメーション | 独自の機能としては持たない(アニメーション用のメソッドはない) | 独自の機能を持つ(アニメーション用のタグがある) |
線の種類や色などを変更するためのプロパティ、および図形を変形するためのメソッドについて説明します。
描画状態は次の要素から構成されます。
カラーネーム | 16進数 |
---|
Canvas では、HTML と同じく、色を名称や16進数で指定することができます。
また、特別な色として、塗らないことを指示する none や 親要素の色を継承する inherit があります。
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>
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>
globalAlpha プロパティは、色の透明度を定義します。
線、テキスト、要素の輪郭または塗りつぶしの透明度を定義する。
プロパティ | 値 | 説明 |
---|---|---|
globalAlpha | 0 ~ 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>
線の太さや種類を設定します。
lineWidth プロパティは、線の太さを定義します。
線の太さを定義する。
プロパティ | 値 | 説明 |
---|---|---|
lineWidth | 0 ~ | 線の太さ (規定値: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の黄色い破線を引いています。
lineCap プロパティは、線の両端の形状を定義します。
線の両端の形状を定義する。
プロパティ | 値 | 説明 |
---|---|---|
lineCap | butt | 線の両端に何もつかない(そのまま)(規定値) |
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>
両端にライン・キャップが付きます。下の例では、分かりやすいように本来の幅で黄色い破線を引いています。
lineJoin プロパティは、線の頂点の形状を定義します。
線の頂点の形状を定義する。
プロパティ | 値 | 説明 |
---|---|---|
lineJoin | miter | 鋭角(そのまま) (規定値) |
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" のときの、鋭角な頂点を面取りする閾値を定義します。
lineJoin="miter" のときの、鋭角な頂点を面取りする閾値を定義する。
プロパティ | 値 | 説明 |
---|---|---|
miterLimit | 0 ~ | 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か所すべての頂点が面取りされていますが、真中は下向きの頂点だけです。
setLineDash メソッドは、破線パターン(直線と空白の長さ)を定義します。この破線パターンを繰り返して線が引かれます。
破線パターン(直線と空白の長さ)を定義する。
引数 | 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 | 0 ~ | 破線パターンの開始位置 (規定値: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 ずつずらして描いています。
図形に対して平行移動や回転などの変形(座標変換)が適用できます。
変形を適用する場合には、先に変形を指定してから図形を描画するという順序になります。変形を後から指定しても、先に描画した図形には適用されません。
また、translate、scale、rotate 関数、あるいはそれらの関数の組み合わせを1つの transform 関数で置き換えることもできます。
平行移動を表すメソッドで、指定した値の分だけ座標軸をその方向にずらします。
この後に描かれる図形はこのずらされた座標系を基準に描かれます。
平行移動する。
transform(1, 0, 0, 1, tx, ty) と記述することもできる。
1 | 0 | tx | ||
0 | 1 | ty | ||
0 | 0 | 1 |
引数 | 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)という座標になります。理解の助けになるように別途描いています。
拡大・縮小を表すメソッドで、左上端を基準に、指定した値の分だけ座標軸方向に拡縮します。
この後に描かれる図形はこの倍率で描かれます。よって、scale(3,0.5) の後で元の倍率で描きたければ scale(1/3,1/0.5) とする必要があります。
拡大・縮小する。
transform(sx, 0, 0, sy, 0, 0) と記述することもできる。
sx | 0 | 0 | ||
0 | sy | 0 | ||
0 | 0 | 1 |
引数 | 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>
グレイの線などは、拡縮前の図形です。理解の助けになるように別途描いています。
回転を表すメソッドで、座標の原点を中心に座標軸を指定した値の分だけ回転します。
座標の原点を中心に回転する。
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) | ||
0 | 0 | 1 |
引数 | 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>
グレイの線は、回転前の図形と座標軸です。うすい青い線は回転後の座標軸です。理解の助けになるように別途描いています。
図形を描画するときに適用する座標の変換行列を作成します。
変形を適用する場合には、先に変形行列を指定してから図形を描画するという順序になります。 変形行列を後から指定しても、先に描画した図形には影響しません。
図形を描画するときに適用する座標の変換行列を現在の変換行列にかけ合わせることによって作成する。
translate、scale、rotate の各関数は transform 関数で記述することができる。
複数の関数を指定した場合は、それぞれの行列の積で求まる値が transform 関数の引数になる。
引数 |
| a | X軸方向の拡縮率 | (変形しない場合は 1) | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
b | Y軸方向の傾斜 | (変形しない場合は 0) | |||||||||||||||||
c | X軸方向の傾斜 | (変形しない場合は 0) | |||||||||||||||||
d | Y軸方向の拡縮率 | (変形しない場合は 1) | |||||||||||||||||
e | Y軸方向の移動距離 | (変形しない場合は 0) | |||||||||||||||||
f | X軸方向の移動距離 | (変形しない場合は 0) | |||||||||||||||||
戻り値 | なし |
図形を描画するときに適用する座標の変換行列を新たに作成する。
translate、scale、rotate の各関数は setTransform 関数で記述することができる。
複数の関数を指定した場合は、それぞれの行列の積で求まる値が setTransform 関数の引数になる。
引数 |
| a | X軸方向の拡縮率 | (変形しない場合は 1) | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
b | Y軸方向の傾斜 | (変形しない場合は 0) | |||||||||||||||||
c | X軸方向の傾斜 | (変形しない場合は 0) | |||||||||||||||||
d | Y軸方向の拡縮率 | (変形しない場合は 1) | |||||||||||||||||
e | Y軸方向の移動距離 | (変形しない場合は 0) | |||||||||||||||||
f | X軸方向の移動距離 | (変形しない場合は 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)
は、これらが表す行列の積になります。 これを式で表すと
| * |
| * |
| ||||||||||||||||||||||||||||||||||||||||||||||
= |
| * |
| |||||||||||||||||||||||||||||||||||||||||||||||
= |
|
よって、context2 の
setTransform(1.732, 1, -0.25, 0.433, 49.634, 28.634) になります。
なお、SVG にはあるんですが、Canvas にはない「傾斜」についても説明しておきます。
SVG では、横方向の傾斜を skewX、 縦方向の傾斜を skewY で実現しています。
Y 軸を指定した角度だけ傾け、横方向に傾斜させます。(Canvas のメソッドではありません。)
横方向に傾斜する。
引数 | 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>
グレイの線は、傾斜前の座標軸や図形です。うすい青い線は傾斜後の座標軸です。理解の助けになるように別途描いています。
X 軸を指定した角度だけ傾け、縦方向に傾斜させます。(Canvas のメソッドではありません。)
縦方向に傾斜する。
引数 | 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>
グレイの線は、変形前の図形と座標軸です。うすい青い線は回転後の座標軸などです。理解の助けになるように別途描いています。
表示する図形や文字列に影を付ける際に使用します。
影の色を指定します。
影の色を定義する。
次の値は代表的な指定方法です。詳しくは、「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>
影のぼかしレベルを指定します(ぼかしレベルであって、ぼかしの範囲ではありません)。
影のぼかしレベルを定義する。
プロパティ | 値 | 説明 |
---|---|---|
shadowBlur | 0 ~ | ぼかしレベル (規定値: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>
左から右に向かって、順にぼかしを強くしています。
影の位置(影を付ける図形からの隔たり)を指定します。
影の位置を定義する。
プロパティ | 値 | 説明 |
---|---|---|
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軸方向ではありません)。
プロパティの状況を保存(save)し、一時的に変更した後、保存した状態に戻す(restore)ことができます。このとき、restore すると最後に save した状態はなくなります。
save と restore は、ネストしていても構いませんが、restore したときに戻る状態は最後に save したものになります。そして、もう一度 restore すると、もししていればその前に save した状態に戻ります。
現在の状態をスタックの最後に加えます。保存される状態には次のものがあります。
現在の状態をスタックの最後に加える。
引数 | なし | |
---|---|---|
戻り値 | なし |
スタックから最後状態を取り出し、現在の状態に設定します(現在の状態が取り出した状態に変更されます)。保存されている状態には次のものがあります。
スタックから最後状態を取り出し、現在の状態に設定する。
引数 | なし | |
---|---|---|
戻り値 | なし |
<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>
矩形を作成するために使用します。
矩形の枠(塗りつぶさない線のみ)を描きます。
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列目は回転させています。
矩形を塗りつぶして描きます。
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列目は回転させています。
矩形で切り抜き透明にします。切り抜かれた後の色は <canvas> の背景色になります。
<canvas> の背景色で矩形を塗りつぶすのと同じです。
矩形の形で切り抜き透明にする
引数 | 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> 要素の背景色である黄色が見えるようになりました。
パスを使用していろいろな図形を定義するために使用します。
Canvas のコンテキストには必ず現在のパスが 1つあります。
パスは、0 個以上のサブパスのリストを持ちます。それぞれのサブパスは、1 つ以上の地点のリストから構成され、直線や曲線で接続されます。そして、サブパスが閉じられているか否かを表すフラグから構成されます。閉じられたサブパスとは、サブパスの終点がサブパスの始点に直線で接続されたものです。
コンテキストが生成されたときには、パスにはサブパスが一つもありません。パスを作成するには、moveTo、lineTo、quadricCurveTo、bezierCurveTo、arcTo、arc を使用します。
また、パスを定義しただけでは図形は描かれません。stroke、fill を使用して枠を描いたり塗りつぶしたりする必要があります。
ちなみに、「11.3 矩形」で説明したメソッドではサブパスは作られません。
パスの開始と終了を宣言するために使用します。
パスの開始を宣言します。つまり、サブパスが 1つもない状態にします。
パスの開始を宣言する
引数 | なし |
---|---|
戻り値 | なし |
<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 で描画しておく必要があります。
パスの終点から始点に向かって直線が引かれたものと見なし、閉じた図形にします。
もし最後の直線が必要ないのなら、次のパスを開始するときも closePath はいりません。closePath なしに、beginPath を実行します。
なお、closePath を実行したら、自動的に新たなパスが開始されたと解釈されるので、beginPath は必要ありません。
パスの終点から始点に向かって直線が引き閉じた図形にする
引数 | なし |
---|---|
戻り値 | なし |
<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 がありますので、終点から始点に向かって直線が引かれ、図形は閉じます。
サブパスの開始座標を指定します。
ただし、rect などのような閉じた図形を定義するメソッドもありますので、moveTo が絶対に必要なわけではありません。
サブパスの開始座標を指定する
引数 | 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) には直線が引かれません。
作成されたパスに従って図形を描画します。
作成されたパスに従って図形の枠(輪郭のみで塗りつぶしません)を描画します。
作成されたパスに従って図形の枠を描画する
引数 | なし |
---|---|
戻り値 | なし |
<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>
作成されたパスや塗り分けルールに従って図形を塗りつぶして描画します。
作成されたパスや塗り分けルールに従って図形を塗りつぶして描画する
引数 | fillRule | 塗りつぶしルール
| ||||
---|---|---|---|---|---|---|
戻り値 | なし |
<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()">
矩形を作成する際に使用します。
strokeRect との違いはサブパスが生成されることです。rect だけでは図形の描画はされません。
矩形を指定する
引数 | 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>
上段左から、細い枠、太い枠、太い破線の枠(太さの指定が引き継がれています)
下段左から、塗りつぶし、塗りつぶしと枠、枠と塗りつぶし(左とは順序が逆)です。
円弧を作成する際に使用します。
円弧を指定する
引数 | x | 円弧の中心の X座標 | ||||
---|---|---|---|---|---|---|
y | 円弧の中心の Y座標 | |||||
r | 円弧の半径 | |||||
startAngle | 開始角度 | ラジアン:X 軸の正の領域から時計回り | ||||
endAngle | 終了角度 | |||||
anticlockwise | 描画の向き
| |||||
戻り値 | なし |
<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 があるので、作成してみます。
円を作成する際に使用します。(Canvas のメソッドではありません。)
円を指定する
引数 | 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>
上段左から、細い枠、太い枠、太い破線の枠(太さの指定が引き継がれています)
下段左から、塗りつぶし、塗りつぶしと枠、枠と塗りつぶし(左とは順序が逆)です。
楕円を作成する際に使用します。(Canvas のメソッドではありません。)
楕円を指定する
引数 | 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>
上段左から、細い枠、太い枠、太い破線の枠(太さの指定が引き継がれています)
下段左から、塗りつぶし、塗りつぶしと枠、枠と塗りつぶし(左とは順序が逆)です。
現在の描画位置から指定した位置に、直線を描くために使用します。
続けて使用すれば多角形を描くこともできます。
直線の終点を指定する
引数 | 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 があるので、作成してみます。
折線を作成する際に使用します。(Canvas のメソッドではありません。)
折線を指定する
引数 | 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>
上段左から、細い枠、太い枠、太い破線の枠(太さの指定が引き継がれています)
下段左から、塗りつぶし、塗りつぶしと枠、枠と塗りつぶし(左とは順序が逆)です。
多角形を作成する際に使用します。(Canvas のメソッドではありません。)
多角形を指定する
引数 | 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>
上段左から、細い枠、太い枠、太い破線の枠(太さの指定が引き継がれています)
下段左から、塗りつぶし、塗りつぶしと枠、枠と塗りつぶし(左とは順序が逆)です。
現在の描画位置から指定された座標と半径から求まる曲線を描くために使用します。
座標と半径から求まる曲線を指定する
引数 | 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>
上段左から、細い枠、太い枠、太い破線の枠(太さの指定が引き継がれています)
下段左から、塗りつぶし、塗りつぶしと枠、枠と塗りつぶし(左とは順序が逆)です。
二次ベジェ曲線を描くために使用します。制御点 (cpx, cpy) を 1 つだけ必要とし、始点(現在の座標)側と終点 (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つの方法で描いてみます。
| |||||||||||||||||||||||||||||||||||||||
|
| ||||||||||||||||||||||||||||||||||||||
なお、グレイの線はポイントを直線で結んだ場合の図形です。 |
三次ベジェ曲線を描くために使用します。制御点(cpx1, cpy1)(cpx2, cpy2)を 2 つにして、始点(現在の座標)側と終点 (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) まで曲線を引いています。
なお、グレイの破線や色の薄い図形などは理解の助けになるように別途描いています。
指定された座標がパスで描画される図形の内側(境界も含む)にあるかどうかを調べる際に使用します。
指定された座標がパスで描画される図形の内側(境界も含む)にあるかどうかを調べる
ただし、座標 (x, y) は変形の影響を受けません。あくまで Canvas の左上が (0, 0) です。
引数 | x | 終点の X座標 | |||
---|---|---|---|---|---|
y | 終点の Y座標 | ||||
fillRule | 塗りつぶしルール
| ||||
戻り値 | 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 メソッドで調べようとしている座標は図形の外側ということになります。
テキストの輪郭を図形として作成します。
テキストの枠(輪郭のみで塗りつぶしません)を描画します。
テキストの枠を描画する際に使用する。
引数 | 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>
破線の交点がテキストを表示している座標です。また、右側は描画領域の幅を指定していますので、その幅の範囲で描画されています。
テキストを塗りつぶして描画します。
テキストを塗りつぶして描画する際に使用する。
引数 | 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>
破線の交点がテキストを表示している座標です。また、右側は描画領域の幅を指定していますので、その幅の範囲で描画されています。
フォントスタイルに関わる属性を指定します。CSS の font と同じように指定します。
フォントスタイルに関わる属性を定義する。
プロパティ | 値 | ||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
font | フォントスタイル(CSS の font と同じように、属性値を空白区切りで組み合わせて指定する。ただし、行の高さは normal に固定されている。)
| ○ | ○ | △ | ○ | ○ | ○ |
詳細は、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>
設定された座標に表示する、テキストの水平方向の位置を指定します。
テキストの水平方向の位置を定義する。
プロパティ | 値 | 説明 |
---|---|---|
textAlign | start | 開始位置揃え (規定値) |
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 は表示する文字列の左と右です。
ベースラインの位置を指定する際に使用します。
ベースラインの位置を定義する。
プロパティ | 値 | 説明 |
---|---|---|
textAlign | top | 上端揃え |
hanging | hanging基底線を利用する(インド系言語) | |
middle | middle基底線を利用する | |
alphabetic | alphabetic基底線を利用する(アルファベット等) (規定値) | |
ideographic | ideographic基底線を利用する(ひらがな、漢字、ハングル等) | |
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 はブラウザによって位置が異なっているようです。
テキストの描画幅を測定する際に使用します。
現在のフォントでテキストを描画した場合の描画幅を取得する。
引数 | 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 プロパティが実数値のこともあるようです。
イメージを描画する際に使用します。イメージの描画は現在のパスには影響を与えません。
イメージを描画する際に使用する。
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()">
ImageData オブジェクトの取得や設定をする際に使用します。
指定範囲の ImageData オブジェクトを Canvas から取得する際に使用します。
ImageData オブジェクトを Canvas から取得する。
引数 | sx | 取得するイメージの X座標 | ||||||
---|---|---|---|---|---|---|---|---|
sy | 取得するイメージの Y座標 | |||||||
sw | 取得するイメージの幅 | |||||||
sh | 取得するイメージの高さ | |||||||
戻り値 | ImageData オブジェクト(主なプロパティは以下の通り)
|
ImageData オブジェクトを Canvas に書き戻す際に使用します。
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()">
ImageData オブジェクトの生成をする際に使用します。
ImageData オブジェクトを生成する。生成されたオブジェクトにあるすべてのピクセルは、透明な黒(rgba(0, 0, 0, 0))となる。
引数 | sw | 生成するイメージの幅 | ||||||
---|---|---|---|---|---|---|---|---|
sh | 生成するイメージの高さ | |||||||
戻り値 | ImageData オブジェクト(主なプロパティは以下の通り)
|
ImageData オブジェクトを生成する。生成されたオブジェクトにあるすべてのピクセルは、透明な黒(rgba(0, 0, 0, 0))となる。
引数 | imagedata | このオブジェクトに含まれるイメージの幅と高さで生成する | ||||||
---|---|---|---|---|---|---|---|---|
戻り値 | ImageData オブジェクト(主なプロパティは以下の通り)
|
<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>
グラデーションは塗り潰しに用いる色を徐々に変化させることで、単色によるものに比べて滑らかな見た目をもたらします。
Canvas においてもグラデーションを線形に掛ける createLinearGradient メソッドと円形に掛ける createRadialGradient メソッドが提供されています。
また、実際にグラデーションを始めるたり終わらせたりする位置や色は、addColorStop メソッドで指定します。
座標 (x1,y1) から座標 (x2,y2) の範囲に線形のグラデーションを描画します。
座標の (0,0) は Canvas の左上です。描画する図形の左上ではありません。
また、変形によって座標軸が移動したような場合は座標軸に合わせてグラデーションも変形します。
座標 (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つの図形はグラデーションの一部を切り取った形で塗りつぶされています。グレイの線がグラデーションの幅を示しています。
右の図はグラデーションのイメージと切り取られた部分を表しています。
中心座標(x1,y1)、半径 r1 から中心座標(x2,y2)、半径 r2 の範囲に円形のグラデーションを描画します。
座標の (0,0) は Canvas の左上です。描画する図形の左上ではありません。
開始円(中心座標(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つの図形はグラデーションの一部を切り取った形で塗りつぶされています。グレイの線がグラデーションの幅を示しています。
右の図はグラデーションのイメージと切り取られた部分を表しています。
stop 要素は、createLinearGradient メソッドや createRadialGradient メソッドなどで定義された勾配ベクトルに基準となる色の位置を指定します。addColorStop 要素間の色は線形に補間されます。なお、addColorStop メソッドで設定された範囲外は通常単色で塗りつぶされます。
0 がグラデーションの開始位置で、1 が終了位置です。
グラデーションに使用する色とその色に変わる位置を指定する。
引数 | offset | 0 ~ 1(色が変わる位置の、グラデーションの開始位置からの割合) | |||||||
---|---|---|---|---|---|---|---|---|---|
color | グラデーションの色 次の値は代表的な指定方法です。詳しくは、「1.2.1 色」 を参照してください。
| ||||||||
戻り値 | なし |
<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つあるので、そこで左右が別のグラデーションになります。
なお、"勾配ベクトル"とその下のグレイの線などは理解の助けになるように別途描いています。
背景パターンとその繰り返し方法を指定する際に使用します。
背景パターンの開始位置は、canvas 要素の左上です。描画する図形の左上ではありませんので注意してください。
背景パターンとその繰り返し方法を指定する。
引数 | image | 描画するイメージ(img 要素、canvas 要素、video 要素、Image オブジェクト) | |||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
repetition | 繰り返し方法
| ||||||||||
戻り値 | 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つのパターンを表しています。このパターンが繰り返し表示されています。
なお、色の薄い背景やグレイの矩形などは、理解の助けになるように別途描いています。
切り抜き指定した領域と、その後にパスで描かれた領域の重なる部分だけが切り抜き表示されます。
切り抜き領域が算出される際には、開いているサブパスも暗黙的に閉じられて切り抜きが適用されますが、 実際にサブパスが閉じられるわけではありません。
パスで切り抜き(クリッピング)する際に使用します。
クリッピングは、図形だけでなく画像やテキストでも行われます。
パスで切り抜き(クリッピング)する際に使用する。
引数 | fillRule | 塗りつぶしルール
| ||||
---|---|---|---|---|---|---|
戻り値 | なし |
<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 します。
合成処理を変更する際に使用します。
それまでに描画された図形などすべてに対して、それ以降に描画する図形などをどのように合成するかを指定します。
図形やイメージの合成方法を指定する。
プロパティ | 値 | 説明 |
---|---|---|
globalCompositeOperation | source-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 によって合成方法が変わります。
グレイの枠は理解の助けになるように別途描いています。
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;">
アニメーションは回転する扇形の部分です。背景の薄い色の画像は別途描いています。
キャンバスに含まれる画像を表す Blob オブジェクトを生成します。Blob (Binary Large Object)とは、一般的に画像や音声などの大きなバイナリデータそのまま格納するためのデータ型です。
キャンバスに含まれる画像を表す 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>