M.Hiroi's Home Page

JavaScript Programming

続・お気楽 JavaScript プログラミング超入門

[ PrevPage | JavaScript | NextPage ]

新しいウインドウ

Web ブラウザの JavaScript 処理系は今開いているウィンドウだけではなく、新しいウィンドウを作って、それを操作することができます。

●window.open()

新しいウィンドウはメソッド window.open() でオープンします。

window.open(url, name, options) => window_object

引数は文字列で、url は表示するページの URL、name はウィンドウ名、options はオプションを指定します。url に空文字列を指定すると、空のウィンドウが生成されます。name と同じ名前のウィンドウが存在する場合、ページはそのウィンドウに表示されます。このほかに、name は HTML の target 属性 (_blank, _self, _parent, _top) を指定することができます。name を省略したり空文字列を指定した場合は _blank と同じ動作になります。

簡単な例を示しましょう。

リスト : 新しいウィンドウ

<button id="win1">Sample01</button>

<script>
let e1 = document.getElementById("win1");
e1.addEventListener('click', () => {
  open('javascript.html');
});
</script>

ボタンをクリックすると拙作のページ JavaScript 超入門 (javascript.html) が新しいタブに表示されます。

●別のウィンドウを開く

別のウィンドウ (子ウィンドウ) を開く場合は、第 3 引数 options にオプション (名前=値) を指定します。複数のオプションを指定する場合はカンマで区切ります。具体的にはウィンドウの大きさや位置を指定してください。

簡単な例を示しましょう。

リスト : 新しいウインドウ (2)

<button id="win2">Sample02</button>

<script>
let e2 = document.getElementById("win2");
e2.addEventListener('click', () => {
  open('javascript.html', "_blank", "width=600, height=400, left=200, top=100");
});
</script>

ボタンをクリックすると新しい子ウィンドウが開き、そこにページが表示されます。

●ウィンドウを閉じる

JavaScript で開いたウィンドウはメソッド close() で閉じることができます。JavaScript 以外の操作で開いたウィンドウは閉じることができません。ご注意くださいませ。

簡単な例を示しましょう。

リスト : ウィンドウを閉じる

<button id="win3">Open</button>
<button id="win4">Close</button>

<script>
let e3 = document.getElementById("win3"),
    e4 = document.getElementById("win4"),
    w3 = null;
e3.addEventListener('click', () => {
  if (w3 == null || w3.closed) {
    w3 = open('javascript.html', "_blank", "width=600, height=400, left=200, top=100");
  }
});
e4.addEventListener('click', () => {
  if (w3 != null && !w3.closed) {
    w3.close();
    w3 = null;
  }
});
</script>

ウィンドウをオープンするボタンとクローズするボタンを用意します。そして、変数 w3 にオープンしたウィンドウのオブジェクトをセットします。ボタン Open をクリックしたとき、w3 が null または プロパティ closed が true ならば、ウィンドウはオープンしていません。メソッド open() でウィンドウを開きます。ボタン Close をクリックしたとき、w3 が null ではなく、かつ w3.colsed が false ならばウィンドウはオープンしています。メソッド close() でウィンドウをクローズします。

それでは実際に試してみてください。

●空ウィンドウに HTML 文書を出力する

空ウィンドウを生成して、そこに HTML 文書を書き込むこともできます。ウィンドウに HTML 文書を書き込むには、document.open() でドキュメントをオープンし、メソッド documnet.write() で HTML 文書を書き込みます。最後に、document.close() でドキュメントをクローズします。open() でドキュメントをオープンすると、既存の HTML 文書は削除されることに注意してください。

簡単な例を示しましょう。

リスト : 空ウィンドウに HTML 文書を出力

<button id="win5">Sample04</button>

<script>
let e5 = document.getElementById("win5"),
    w5 = null;
e5.addEventListener('click', () => {
  if (w5 == null || w5.closed)
    w5 = open("", "_blank", "width=400, height=100, left=200, top=100");
  let d5 = w5.document,
      date = (new Date()).toLocaleString();
  d5.open();
  d5.write(`<html><body><p>このウィンドウは ${date} にオープンしました</p></body></html>`);
  d5.close();
});
</script>

変数 w5 にオープンしたウィンドウのオブジェクトをセットします。ボタンがクリックされたら、ウィンドウが存在するかチェックします。ウィンドウがなければ open() でウィンドウをオープンします。次に、w5.document でドキュメントオブジェクトを取得して変数 d5 にセットします。あとは、d5.open() でドキュメントをオープンし、d5.write() でHTML 文書を書き込みます。ここではウィンドウをオープンした時間を表示します。最後に d5.close() でドキュメントをクローズします。

それでは実際に試してみましょう。

ボタンをクリックするたびに日付 (時間) が変わっていきます。

●ウィンドウの位置

ウィンドウの位置 (左上隅の座標) はプロパティ screenX, screenY で取得することができます。メソッド moveTo(), moveBy() を使うとウィンドウを移動させることができます。

window.moveTo(x, y)
window.moveBy(dx, dy)

moveTo() の引数は移動先の座標 (x, y) を指定します。moveBy() の引数は移動量 dx, dy を指定します。

簡単な例を示しましょう。

リスト : ウィンドウの移動

<button id="win6">Sample05</button>

<script>
let e6 = document.getElementById("win6"),
    w6 = null;
e6.addEventListener('click', () => {
  if (w6 == null || w6.closed) { 
    w6 = open("", "_blank", "width=100, height=100");
    function moveWin(x, y) {
      if (x < 600) {
        w6.moveTo(x, y);
        setTimeout(() => moveWin(x + 5, y + 5), 500);
      }
    }
    moveWin(5, 5);
  }
});
</script>

ボタンをクリックするとウィンドウを生成して、それを左上から右下へ移動します。

●ウィンドウの大きさ

ウィンドウの大きさは次のプロパティで取得することができます。

メソッド resizeTo(), resizeBy() を使うと、ウィンドウの大きさを変更することができます。

resizeTo(width, height)
resizeBy(dw, dh)

resizeTo() はウィンドウの大きさを数値で指定します。100 より小さな値を指定することはできません。resizeBy() は変化量 dw, dh を数値で指定します。

簡単な例を示しましょう。

リスト : ウィンドウのリサイズ

<button id="small">Small</button>
<button id="medium">Medium</button>
<button id="large">Large</button>

let w7 = null,
    e7 = document.getElementById("small"),
    e8 = document.getElementById("medium"),
    e9 = document.getElementById("large");
function openWin() {
  w7 = open("", "_blank", "width=400, height=300");
}
e7.addEventListener('click', () => {
  if (w7 == null || w7.closed) openWin();
  w7.resizeTo(200, 150);
})
e8.addEventListener('click', () => {
  if (w7 == null || w7.closed) openWin();
  w7.resizeTo(400, 300);
})
e9.addEventListener('click', () => {
  if (w7 == null || w7.closed) openWin();
  w7.resizeTo(600, 450);
})

ボタンを 3 つ用意します。Small を押すとウィンドウの大きさを 200 * 150 に、Medium を 400 * 300 に、Large を押すと 600 * 450 に変更します。

●親ウィンドウを操作する

window.open() で子ウィンドウを開いたとき、子ウィンドウのプロパティ window.opener には親ウィンドウのオブジェクトがセットされます。このウィンドウオブジェクトを使って親ウィンドウを操作したり、DOM を使ってドキュメントを書き換えたりすることができます。

簡単な例を示しましょう。子ウィンドウを開いて、色を選択するボタンを表示します。ボタンを押したら、親ウィンドウのメッセージを指定した色に変更します。次のリストを見てください。

リスト : 親ウィンドウ

<p id="parentMsg">hello, world</p>
<button id="win7">Change Color</button>

<script>
let w10 = null,
    e10 = document.getElementById("win7");
e10.addEventListener('click', () => {
  if (w10 == null || w10.closed) {
    w10 = open("./dom10.html", "_blank", "width=400, height=400");
  }
});
</script>

親ウィンドウでは、メッセージ hello, world を表示して、子ウィンドウを開くボタンを用意します。メッセージには id に parentMsg を設定します。ボタンを押したら dom10.html を子ウィンドウに表示します。

リスト : 子ウィンドウ

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>続・お気楽 JavaScript 超入門</title>
</head>
<body>
<p id="msg">親ウィンドウのメッセージの色を変更します</p>
<button onclick="changeColor('red')">Red</button>
<button onclick="changeColor('blue')">Blue</button>
<button onclick="changeColor('green')">Green</button>
<script>
function changeColor(color) {
  let w = window.opener;
  if (w && !w.closed) {
    w.document.getElementById("parentMsg").style.color = color;
  }
}
</script>
</body>
</html>

子ウィンドウでは、ボタンを 3 つ用意して、クリックしたら関数 changeColor() を呼び出します。今回はコールバック関数の設定を HTML のイベント属性 onclick で行いました。changeColor() では、最初に親ウィンドウが存在するかチェックします。そうであれば getElementById() で id が parentMsg の要素を取得して、その色を color に変更します。

それでは実際に試してみてください。

hello, world

なお、このプログラムはサーバー上で実行しないと動作しません。Google Chrome の場合、起動時に次のオプションを指定すると、サーバー上でなくても動作します。

--allow-file-access-from-files

ご注意くださいませ。


Canvas

「Canvas (キャンバス)」は HTML5 で導入された機能です。JavaScript を使って Web ブラウザ上で 2D グラフィックを描画することができます。今回は Canvas の基本的な使い方を簡単に説明します。

●Canvas の使い方

Canvas のタグは <canvas></canvas> です。JavaScript から操作しやすいように id を設定するといいでしょう。あと、幅 (width) と高さ (height) を指定します。省略した場合、width=300, height=150 に設定されます。

簡単な例を示しましょう。

リスト : Canvas の簡単な例

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>続・お気楽 JavaScript 超入門</title>
  <style type="text/css">
    canvas { border: 1px solid black; }
  </style></head>
<body>
<h1 id="msg1">Canvas 入門</h1>
<canvas id="can" width=400 height=200>
Canvas に対応したブラウザをお使いください。
</canvas>
<script src="canvas01.js"></script>
</body>
</html>
リスト : canvas01.js

function draw() {
  let c = document.getElementById("can");
  if (!c.getContext) return false;
  let ctx = c.getContext("2d");
  ctx.fillRect(10, 10, 180, 180);     // 塗りつぶし
}

window.onload = draw();

head の中の style でキャンバスを黒線で囲います。canvas タグでは属性 id="can", width=400, height= 200 を設定します。Web ブラウザが Canvans に対応していない場合、canvas タグの間の文書や HTML 要素が表示されます。そして、</body> タグの直前でスクリプトファイル canvas01.js を読み込みます。実際の描画はこのスクリプトファイルで行います。

描画処理は関数 drow() で行います。最初に Canvas のオブジェクトを getElementById() で取得します。次に、メソッド getContext() で「描画コンテキスト」を取得します。引数には "2d" を指定します。このメソッドの有無で Web ブラウザが Canvas に対応しているかチェックすることができます。描画コンテキストには描画用のメソッドがいろいろ用意されていて、fillRect() は矩形 (塗りつぶし) を描画します。これはあとで説明します。

最後に、window.onload に draw() を登録します。Web ブラウザが HTML ファイルの読み込みを完了すると、この関数が実行されます。

それでは実際に試してみましょう。

Sample01

黒く塗りつぶされた正方形が表示されます。

●矩形の描画

まずは最初に、矩形 (長方形) を描画するメソッドから説明しましょう。

strokeRect(x, y, w, h)
fillRect(x, y, w, h)
clearRect(x, y, w, h)

strokeRect() は矩形 (枠) 描画し、fillRect() は矩形の中を塗りつぶします。clearRect() は矩形の中を透明にします。x, y は矩形左上の座標です。キャンバスの左上隅が原点 (0, 0) で、右下隅が (width-1, height-1) になります。w, h は幅と高さを表します。

線や塗りつぶしの色はプロパティ strokeStyle, fillStyle で指定します。

ctx.strokeStyle = color
ctx.fillStyle = color

color は CSS と同じ指定方法です。rgb, rgba を使って指定することもできます。

rgb(red, green, blue)
rgba(red, green, blue, alpha)

引数 red, green, blue は整数値 (0 - 255) またはパーセント (0% - 100%) で指定します。alpha は透明度を表していて、小数 (0.0 - 1.0) で指定します。なお、rgb(), rgba() は関数ではありません。プロパティにセットするときは文字列 "rgb(...)", "rgba(...)" で行ってください。

簡単な例を示しましょう。

リスト : 矩形の描画

function draw() {
  let c = document.getElementById("can");
  if (!c.getContext) return false;
  let ctx = c.getContext("2d");
  ctx.strokeStyle = 'red';
  ctx.strokeRect(10, 10, 50, 50);
  ctx.fillStyle = 'green';
  ctx.fillRect(70, 10, 50, 50);
  ctx.fillStyle = 'blue';
  ctx.fillRect(130, 10, 50, 50);
  ctx.clearRect(140, 20, 30, 30);
}

window.onload = draw();

M.Hiroi は Tcl/Tk, Python/Tkinter, Ruby/Tk など GUI ツールキット Tk を使ったことがあります。Tk の場合、色などの指定はメソッドの引数で行うのですが、Canvas は描画コンテキストのプロパティに色をセットしてからメソッドを呼び出して図形を描画します。それでは実行してみましょう。

Sample02

●線の描画

矩形以外の図形は「パス」を使って描画します。パスはペンの通り道と考えてください。点と点を線や曲線でつなげて図形を描画します。パスの指定方法を以下に示します。

  1. beginPath() でパスを生成する。
  2. moveTo(x, y) でペンを移動する。
  3. メソッドで線や曲線などを設定する。
  4. closePath() でパスを閉じる。
  5. fill() で囲まれた領域を塗りつぶす。
  6. stroke() で線を描画する。

線はメソッド lineTo() で設定します。

lineTo(x, y)

lineTo() はペンの現在位置から座標 (x, y) まで直線を引きます。ペンの位置は (x, y) に移動します。

簡単な例を示しましょう。

リスト : 線の描画

function draw() {
  let c = document.getElementById("can");
  if (!c.getContext) return false;
  let ctx = c.getContext("2d");
  ctx.strokeStyle = 'red';
  ctx.beginPath();
  ctx.moveTo(10, 10);
  ctx.lineTo(380, 10);
  ctx.lineTo(10, 180);
  ctx.closePath();
  ctx.stroke();

  ctx.fillStyle = 'green';
  ctx.beginPath();
  ctx.moveTo(390, 10);
  ctx.lineTo(10, 190);
  ctx.lineTo(390, 190);
  ctx.fill();
}

window.onload = draw();

fill() の場合、closePath() でパスを閉じなくても始点と終点を結んだ領域を塗りつぶしてくれます。なお、fill() したあとで stroke() を実行すると、strokeStyle の色で図形の輪郭を描画することができます。この場合は closePath() でパスを閉じでください。

Sample03

線の太さはプロパティ lineWidth で指定することができます。

リスト : lineWidth の設定

function draw() {
  let c = document.getElementById("can");
  if (!c.getContext) return false;
  let ctx = c.getContext("2d");
  for (let i = 0; i < 10; i++) {
    ctx.lineWidth = i + 1;
    ctx.beginPath();
    ctx.moveTo(10, 10 + i * 20);
    ctx.lineTo(380, 10 + i * 20);
    ctx.stroke();
  }
}

window.onload = draw();
Sample04

この他にも、いろいろなスタイルを指定することができます。詳細は 参考 URL 1 をお読みください。

●円弧の描画

円 (円弧) はメソッド arc() で描画します。

arc(x, y, r, start, end [, dir])

引数 x, y は中心の座標、r は半径、start は開始位置、end は終端位置、dir は方向 (デフォルトは時計回り) を表します。start, end は度数ではなくラジアンで指定します。

簡単な例を示します。

リスト : 円の描画

function draw() {
  let c = document.getElementById("can");
  if (!c.getContext) return false;
  let ctx = c.getContext("2d");
  ctx.beginPath();
  ctx.arc(50, 50, 50, 0, Math.PI * 2);
  ctx.stroke();

  ctx.fillStyle = 'green';
  ctx.beginPath();
  ctx.arc(150, 50, 50, 0, Math.PI * 2);
  ctx.fill();

  ctx.strokeStyle = 'red';
  ctx.lineWidth = 4;
  ctx.beginPath();
  ctx.arc(250, 50, 50, 0, Math.PI * 1.5);
  ctx.closePath();
  ctx.stroke();

  ctx.fillStyle = 'blue';
  ctx.beginPath();
  ctx.arc(350, 50, 50, 0, Math.PI);
  ctx.fill();
}

window.onload = draw();
Sample05

●ベジェ曲線

ベジェ曲線はコンピュータ上で滑らかな曲線を描画するためによく使用されます。ベジェ曲線はいくつかの制御点を指定して、それに沿うような滑らかな曲線を描きます。Canvas には制御点を一つ指定する二次ベジェ曲線と、二つ指定する三次ベジェ曲線をサポートしています。

quadraticCurveTo(cp1x, cp1y, x, y)
bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)

quadraticCurveTo() は現在のペンの位置から終端 x, y へ、cp1x, cp1y で指定した制御点を使用して二次ベジェ曲線を描きます。bezierCurveTo() は、cp1x, cp1y と cp2x, cp2y で指定した制御点を使用して三次ベジェ曲線を描きます。

簡単な例を示します。

リスト : ベジェ曲線

function draw() {
  let c = document.getElementById("can");
  if (!c.getContext) return false;
  let ctx = c.getContext("2d");
  ctx.strokeStyle = 'black';
  ctx.beginPath();
  ctx.moveTo(10, 10);
  ctx.lineTo(390, 10);
  ctx.lineTo(390, 190);
  ctx.lineTo(10, 190);
  ctx.closePath();
  ctx.stroke();

  ctx.strokeStyle = 'blue';
  ctx.beginPath();
  ctx.moveTo(10, 10);
  ctx.quadraticCurveTo(390, 10, 390, 190);
  ctx.stroke();

  ctx.strokeStyle = 'green';
  ctx.beginPath();
  ctx.moveTo(10, 10);
  ctx.quadraticCurveTo(10, 190, 390, 190);
  ctx.stroke();

  ctx.strokeStyle = 'red';
  ctx.beginPath();
  ctx.moveTo(10, 190);
  ctx.quadraticCurveTo(10, 10, 390, 10);
  ctx.stroke();

  ctx.strokeStyle = 'purple';
  ctx.beginPath();
  ctx.moveTo(10, 190);
  ctx.quadraticCurveTo(390, 190, 390, 10);
  ctx.stroke();  
}

window.onload = draw();
Sample06

●テキストの描画

テキストは次のメソッドで描画します。

fillText(string, x, y)
strokeText(string, x, y)

fillText() は座標 x, y の位置に文字列 string を塗りつぶしで描画します。strokeText() は文字の輪郭だけを描画します。

簡単な例を示します。

リスト : テキストの描画

function draw() {
  let c = document.getElementById("can");
  if (!c.getContext) return false;
  let ctx = c.getContext("2d");
  ctx.font = "48px serif";
  ctx.beginPath();
  ctx.fillText("hello, world", 10, 50);

  ctx.beginPath();
  ctx.strokeText("hello, world", 10, 100);
}

window.onload = draw();

プロパティ font はフォントを指定します。形式は CSS と同じです。

Sample07

●画像の表示

Canvas は画像を表示することもできます。表示できる画像のタイプは HTML タグでいうと <img>, <video>, <canvas> の 3 種類ありますが、ここでは <img> の画像を表示してみましょう。画像はメソッド drawImage() で表示します。

drawImage(img, x, y [, width, height])

引数 img は画像を保持する HTMLImageElement、x, y は表示する位置を表します。width, height を指定すると、その大きさに画像を拡大 (または縮小) して表示します。

簡単な例を示しましょう。

リスト : 画面の表示

function draw() {
  let c = document.getElementById("can");
  if (!c.getContext) return false;
  let ctx = c.getContext("2d"),
      img = new Image();
  img.onload = () => {
    ctx.drawImage(img, 0, 0);
    ctx.drawImage(img, 0, 50, img.naturalWidth * 2, img.naturalHeight * 2);
  }
  img.src = "ruby_img/button0.png"
}

window.onload = draw();

new Image() で HTMLImageElement を生成して変数 img にセットします。それから、img.src に URL をセットして、画像ファイルを読み込みます。これは拙作のページ お気楽 Ruby/Tk 超入門 で作成した画像です。画像の表示は img.onload にセットしたアロー関数で行います。画像の読み込みが完了したとき、このアロー関数が実行されます。最初は画像をそのまま表示します。その下に画像を縦横 2 倍に拡大して表示します。naturalWidth, naturalHeight は画像のサイズを表すプロパティです。

それでは実際に試してみてください。

Sample08

●グラデーション

Canvas は色を塗るときにグラデーション (gradation) を指定することができます。グラデーションはある色から他の色に滑らかに変化させていく塗り方です。グラデーションは次に示すメソッドでグラデーションを表すオブジェクト (Canvas Gradient Object) を生成し、それをプロパティ fillStyle にセットします。

createLinearGradient(x1, y1, x2, y2)         => CanvasGradientObject 
createRadialGradient(x1, y1, r1, x2, y2, r2) => CanvasGradientObject 

createLinearGradient() は始点 (x1, y1) と終点 (x2, y2) を結んだ直線に沿ってグラデーションをかけます。createRadialGradient() は中心 (x1, y1) 半径 r1 の円周上から中心 (x2, y2) 半径 r2 の円周上に向かって放射状にグラデーションをかけます。

色の指定はメソッド addColorStop() で行います。

CanvasGradientObject.addColorStop(位置, 色)

位置は数値 (0.0 - 1.0) で指定します。0.0 が始点、1.0 が終点を表します。たとえば、0.0 に青、0.5 に黄色、1.0 に赤を指定すると、色は青から黄色に変わり、中間点を過ぎると黄色から赤に変わっていきます。

簡単な例を示しましょう。

リスト : グラデーション

function draw() {
  let c = document.getElementById("can");
  if (!c.getContext) return false;
  let ctx = c.getContext("2d"),
      grd1 = ctx.createLinearGradient(10,10,10,190),
      grd2 = ctx.createLinearGradient(70,10,390,10),
      grd3 = ctx.createLinearGradient(70,80,180,190),
      grd4 = ctx.createLinearGradient(190,190,300,80);
  grd1.addColorStop(0, 'blue');
  grd1.addColorStop(0.5, 'yellow');
  grd1.addColorStop(1, 'red');
  ctx.fillStyle = grd1;
  ctx.fillRect(10, 10, 50, 180);

  grd2.addColorStop(0, 'red');
  grd2.addColorStop(0.5, 'yellow');
  grd2.addColorStop(1, 'blue');
  ctx.fillStyle = grd2;
  ctx.fillRect(70, 10, 320, 60);

  grd3.addColorStop(0, 'blue');
  grd3.addColorStop(0.3, 'cyan');
  grd3.addColorStop(0.7, 'yellow');
  grd3.addColorStop(1, 'red');
  ctx.fillStyle = grd3;
  ctx.fillRect(70, 80, 110, 110);

  grd4.addColorStop(0, 'blue');
  grd4.addColorStop(0.3, 'cyan');
  grd4.addColorStop(0.7, 'yellow');
  grd4.addColorStop(1, 'red');
  ctx.fillStyle = grd4;
  ctx.fillRect(190, 80, 110, 110);

  let grd5 = ctx.createRadialGradient(150,250,10,200,300,100);
  grd5.addColorStop(0, 'red');
  grd5.addColorStop(0.5, 'yellow');
  grd5.addColorStop(1, 'blue');
  ctx.fillStyle = grd5;
  ctx.fillRect(10, 200, 380, 180);
}

window.onload = draw();

変数 grd1 には縦方向のグラデーションをセットします。grd2 は横方向、grd3 は左上隅から右下隅、grd2 は左下隅から右上隅にグラデーションをかけます。そして、addColorStop() で色を指定して、プロパティ fillStyle にこれらの変数をセットします。最後に fillRect() を実行すると、矩形の色にグラデーションがかかります。createRadialGradient() は範囲を円で指定するだけで、あとは同じです。

Sample09

●図形の変形

Canvas は座標軸を変換することで図形を変形させることができます。一番簡単なメソッドは原点を移動する translate() です。

translate(dx, dy)

translate() は現時点の原点 (0, 0) を x 方向に dx, y 方向に dy だけ移動します。簡単な例を示しましょう。

リスト : translate() の使用例

function draw() {
  let c = document.getElementById("can");
  if (!c.getContext) return false;
  let ctx = c.getContext("2d");
  ctx.fillStyle = "rgba(0, 255, 0, 0.5)";
  for (let x = 0; x < 10; x++) {
    ctx.fillRect(0, 0, 100, 100);
    ctx.translate(30, 30);
  }
}

window.onload = draw();

fillRect() は (0, 0) から一辺が 100 の正方形を描画していますが、translate() で原点を (+30, +30) 移動するので、左上から右下に向かって 10 個の正方形が重なり合って描画されます。

Sample10

メソッド rotate() は原点を中心に座標を回転します。

rotate(rad)

rad の単位はラジアンで、正の値を与えると時計回りで、負の値を与えると反時計回りで回転します。簡単な例を示しましょう。

リスト : rotate() の使用例

function draw() {
  let c = document.getElementById("can");
  if (!c.getContext) return false;
  let ctx = c.getContext("2d");
  ctx.fillStyle = "rgba(255, 0, 0, 0.5)";
  ctx.translate(200, 200);
  for (let x = 0; x < 12; x++) {
    ctx.fillRect(0, 0, 200, 25);
    ctx.rotate(Math.PI / 6);
  }
}

window.onload = draw();

最初に translate() で原点を Canvas の中心 (200, 200) に移動します。そして、200 * 50 の長方形を原点から描画します。あとは、rotate() で時計回りに座標を回転すれば、原点を中心に 12 個の長方形が描画されます。

Sample11

メソッド scale() は横方向と縦方向の倍率を指定します。1 より大きな値を与えれば拡大し、1 よりも小さな値を与えれば縮小します。

scale(x, y)

引数 x が横方向の倍率、y が縦方向の倍率です。負数を与えると座標が反転します。たとえば scale(1, -1) とすると、左下隅が原点 (0, 0) になるので、数学でお馴染みのデカルト座標になります。

簡単な例を示しましょう。

リスト : scale() の使用例

function draw() {
  let c = document.getElementById("can");
  if (!c.getContext) return false;
  let ctx = c.getContext("2d");
  ctx.translate(200, 200);
  ctx.beginPath();
  ctx.arc(0, 0, 100, 0, Math.PI * 2);
  ctx.stroke();

  ctx.scale(2, 1);
  ctx.beginPath();
  ctx.arc(0, 0, 100, 0, Math.PI * 2);
  ctx.stroke();

  ctx.scale(0.5, 2);
  ctx.beginPath();
  ctx.arc(0, 0, 100, 0, Math.PI * 2);
  ctx.stroke();
}

window.onload = draw();

原点を Canvas の中央に設定し、半径 100 の円を描画します。次に、scale(2, 1) で横方向を 2 倍にして描画すると横に長い楕円形になります。その後、scale(0.5, 2) とすると、横方向の倍率は元に戻り、縦方向の倍率が 2 倍になるので、縦に長い楕円形になります。

Smaple12

●状態の保存と復元

図形のスタイルや座標の変換など、Canvas の状態はメソッド save() で保存して、restore() で元に戻すことができます。save() は何度も呼び出すことができて、状態はスタックに保存されます。save() が PUSH で restore() が POP に相当します。

簡単な例を示しましょう。

リスト : 状態の保存と復元

function draw() {
  let c = document.getElementById("can");
  if (!c.getContext) return false;
  let ctx = c.getContext("2d");
  ctx.translate(200, 200);
  for (let z = 0.2; z <= 2.0; z += 0.2) {
    ctx.save();
    ctx.scale(z, 1);
    ctx.beginPath();
    ctx.arc(0, 0, 100, 0, Math.PI * 2);
    ctx.stroke();
    ctx.restore();
    ctx.save();
    ctx.scale(1, z);
    ctx.beginPath();
    ctx.arc(0, 0, 100, 0, Math.PI * 2);
    ctx.stroke();
    ctx.restore();
  }
}

window.onload = draw();

縦横の倍率を 0.2 刻みで変更します。倍率は変数 z に格納します。最初に、倍率 1.0 の状態を save() で保存しておきます。次に、scale(z, 1) で倍率を変更して描画したあと、restore() で元の状態に戻します。これで z * 1.0 の倍率で円を描画することができます。

Sample13

このほかに、変換行列を指定するメソッド transform() や setTransform() があります。詳細は Transformations - ウェブデベロッパーガイド | MDN をお読みくださいませ。

●影を付ける

Canvas は図形に影 (shadow) を付けることができます。影を付けるには次のプロパティを指定します。

shadowColor は影の色、shadowBlur はぼかし量を数値で指定します。0 を指定すると、ぼかしは無効になります。shadowOffsetX, shadowOffsetY は影のずれを指定します。

簡単な例を示しましょう。

リスト : 影を付ける

function draw() {
  let c = document.getElementById("can");
  if (!c.getContext) return false;
  let ctx = c.getContext("2d");
  ctx.shadowColor = "gray";
  ctx.shadowBlur = 2;
  ctx.shadowOffsetX = 5;
  ctx.shadowOffsetY = 5;

  ctx.fillStyle = "green";
  ctx.fillRect(10, 10, 200, 200);

  ctx.font = "48px serif";
  ctx.fillStyle = "black";
  ctx.beginPath();
  ctx.fillText("hello, world", 10, 280);

  let img = new Image();
  img.onload = () => {
    ctx.drawImage(img, 10, 300);
  }
  img.src = "ruby_img/button0.png"
}

window.onload = draw();

矩形、テキスト、画像に影を付けます。プログラムは簡単なので説明は割愛します。実際に試してみてください。

Sample14

●おわりに

Canvas の基本的な機能を簡単に説明しました。このほかにも、Canvas にはいろいろな機能があるので興味のある方は調べてみてください。

●参考 URL

  1. Canvas API - HTML | MDN
  2. HTML5時代のJavaScript入門, (パズルネット智慧さん)
  3. JavaScriptによるHTML5プログラミング入門, (掌田津耶乃さん)
  4. ベジェ曲線 - Wikipedia

Copyright (C) 2017 Makoto Hiroi
All rights reserved.

[ PrevPage | JavaScript | NextPage ]