現在のビジネス手法は、Web およびクラウドを利用するように極めて大きな変化を遂げていますが、HTML5 はこの変化を反映したものとなっています。HTML5 での変更内容にスポットライトを当てるこの 4 回連載の最後の記事では、HTML5 の Canvas 要素について紹介し、サンプルを使ってその機能を具体的に説明します。

Grace Walker, IT Consultant, Walker Automated Services

イリノイ州シカゴにある Walker Automated Services の共同経営者である Grace Walker は、さまざまな経歴と幅広い経験を持つ IT コンサルタントです。IT 業界では、マネージャー、アドミニストレーター、プログラマー、インストラクター、ビジネス・アナリスト、テクニカル・アナリスト、システム・アナリスト、Web 開発者としての経歴を持ち、その分野は通信、教育、金融サービス、ソフトウェアなど多岐に渡ります。



2011年 8月 05日

勇敢にもデザイナーと開発者を兼ねた HTML5 作成者の役割は、効果的な RIA (Rich Internet Application: リッチ・インターネット・アプリケーション) を作成すること (特に、リッチな UI を作成すること) です。実質的には、サイトの所有者、その所有者が使用するエージェント、そしてそのサイトのユーザーとの間の (ネットワークを通じた) 対話を容易にするための、システム全体にわたる体系的な機能強化を行うことです。

RIA は優れたユーザー・エクスペリエンスを提供する手段となるため、ネットを中心とするあらゆる事業の成功に欠かせないものとなっています。本質的に、ネット中心のアクティビティーは多かれ少なかれ、互いに連携するものです。マーケティングやマネージメントをはじめとする、あらゆるレベルで組織が成功するためには、ネットワークを通じた連携を優れた方法で実現することが欠かせません。サイトが訪問者の高い期待に応えられるかどうかは、そのほとんどが効率性にかかっています。

すでにおわかりのように、HTML5 は、電気通信、統一言語、ユビキタス・コンピューティング、そしてオープン・システムを 1 つに集めた (クロス・プラットフォームの機能による) 協調的な「1 つの Web 世界」を対象として作成されたものです。連載のこれまでの 3 回の記事では、RIA を系統的かつ論理的に作成するための基礎を培う目的で、セマンティクス、適切なコーディング手法、必要不可欠な変換プロセスで入力が果たす役割、そしてサイト管理のベスト・プラクティスに焦点を当ててきました。これらの記事で共通するメッセージは、Web サイトの所有者の組織目標を達成するには、リッチなユーザー・エクスペリエンスを生み出し、管理することが極めて重要であるということです。HTML5 の Canvas は、効果的な RIA の開発において重要な役割を果たします。

よく使われる頭文字語

  • 2D: Two-dimensional
  • Ajax: Asynchronous JavaScript + XML
  • API: Application Programming Interface
  • HTML: HyperText Markup Language
  • HTML5: HTML Version 5
  • UI: User Interface

Canvas の紹介

HTML5 Canvas は、描画およびアニメーションに極めて重宝する要素です。Canvas は JavaScript を使用して、グラフィックを直接ページに描画します。Canvas はユーザーが定義して制御する矩形の領域であり、2D の形状とビットマップ画像をスクリプトによって動的にレンダリングすることを可能にします。

UI や図形、写真アルバム、チャート、グラフ、アニメーション、そして組み込み描画のアプリケーションを拡張して素晴らしいビジュアル素材を作成するには、HTML5 の Canvas は申し分のない要素となります。Canvas 要素では、さまざまな方法でパス、矩形、円、文字を描画することができるためです。


キャンバス座標

キャンバスに描画するには、グリッドあるいは座標空間を十分に理解しておく必要があります。空間領域での幅と高さの値はピクセル単位で指定します。キャンバスは x 座標と y 座標を中心に作成されます。キャンバス座標 x=0, y=0 は、左上隅を指します。

矩形のキャンバス領域は、デフォルトで幅 300 ピクセル、高さ 150 ピクセルに設定されますが、ユーザーが幅と高さを指定して、Canvas 要素のサイズを決定することもできます。x 座標と y 座標は、図 1 のように実装されます。

図 1. キャンバス座標
正方形と、その対角線、そして対辺の中点を結ぶ縦横の線が引かれており、その交点に座標が示されています。

図 1 に示されている幅 100 ピクセル、高さ 100 ピクセルのキャンバス領域について、以下に説明します。

  • 左上隅の座標は x=0, y=0 です。
  • x 値は横方向に増加し、y 値は縦方向に増加します。
  • 右下隅は x=100, y=100 です。
  • 中心点は x=50, y=50 です。

開始手順

キャンバスに描画するには、何よりも先に、HTML ファイルにキャンバスを定義しなければなりません。それには、<canvas> タグを通じて HTML5 Canvas API を利用して画像を描画する JavaScript コードを作成します。

<canvas> タグの基本的な構造は以下のとおりです。

<canvas id="myCanvas" width="200" height="200"></canvas>

canvas 要素自体には、width および height という 2 つの属性があります。それに加え、Canvas は主要なすべての HTML5 属性 (classidnameなど) を使用することができます。上記のコードでは、id 属性が使用されています。ここで作成された canvas id を使用して、JavaScript はどのキャンバスに描画するかを特定します。JavaScript は該当するキャンバスを判断するために、以下の document.getElementById() メソッドを使用します。

var canvas = document.getElementById("myCanvas");

あらゆるキャンバスには、コンテキスト定義が必要です (以下を参照)。現在のところ、正式な仕様で認識されるのは 2D 環境だけに限られています。

var context = canvas.getContext("2d");

キャンバスを特定して、そのコンテキストを指定した後は、早速、描画を開始することができます。


描画ツール、エフェクト、および変形

この記事では、HTML5 Canvas のさまざまな描画ツール、エフェクト、および変形について説明します。描画ツールについては、以下を取り上げます。

  • 矩形
  • ベジェ曲線および二次曲線
  • 円および半円

使用する Canvas エフェクトには、以下のものがあります。

  • 塗りつぶし、ストローク
  • 線形グラデーションおよび円形グラデーション

変形のセクションでは、以下の変形機能について説明します。

  • 伸縮
  • 回転
  • 移動

線を描画する

キャンバスに線を描画するには、以下の moveTo()lineTo()、および stroke() メソッドを使用します。さらに beginPath() メソッドを使用して、現在のパスをリセットします。

  • context.beginPath();
  • Context.moveTo(x,y);
  • Context.lineTo(x,y);
  • Context.stroke(x,y);

beginPath() メソッドは、新しいパスを開始します。異なるサブパスで新しい線を描画するには、まず beginPath() を使用して、その後に新しい描画の始点が続くことを示します。最初の線を描画するときには、beginPath() メソッドを呼び出す必要はありません。

moveTo() メソッドは、新しいサブパスの始点を指定します。サブパスを作成するのは、lineTo() メソッドです。線の外観は、lineWidth および strokeStyle で変更することができます。lineWidth 要素は線の太さを変更し、strokeStyle は線の色を変更します。

図 2 に、それぞれ青、緑、紫で描画した 3 本の線を示します。

図 2. 3 色の線が描画されたキャンバス
3 色の線が描画されたキャンバス

図 2 の線は、リスト 1 に記載するコードによって作成されました。両端が丸くなっている青の線を作成するには、最初に context.beginPath() を使用して新規パスが始まることを示します。これに続き、以下のメソッドを使用します。

  • context.moveTo(50, 50): パスの始点を (x=50, y-50) に設定します。
  • context.lineTo(300,50): 線の終点を指定します。
  • context.lineWidth = 10: 線の幅を指定します。
  • context.strokeStyle = "#0000FF": 線の色を指定します。
  • context.lineCap = "round": 線の両端を丸くします。
  • context.stroke(): 実際にキャンバス上に線を描画します。

3 本の線の長さはすべて 50 ピクセルですが、ライン・キャップ (線端の形状) が異なるために、目に映る長さは同じには見えません。ライン・キャップには、以下の 3 つの選択肢があります。

  • Context.round (青の線で使用)
  • Context.square (緑の線で使用)
  • Context.butt (紫の線で使用。デフォルト)

デフォルト値は、butt キャップです。round または square キャップ・スタイルを使用すると、線の長さは、線の幅の分だけ長くなります。例えば、長さ 200 ピクセル、幅 10 ピクセルの線に round または square キャップ・スタイルを指定すると、最終的な線の長さは 210 ピクセルになります。これらのキャップによって、線の両端にはそれぞれ 5 ピクセルが追加されるためです。長さ 200 ピクセル、幅 20 ピクセルの線に round または square キャップ・スタイルを指定した場合には、線の両端にそれぞれ 10 ピクセルが追加され、線の長さは 220 ピクセルになります。

線がどのように描画されるかを十分に理解するために、リスト 1 のコードの値をいろいろと変えて実行してみてください。

リスト 1. キャンバス上に異なる色の 3 本の線を描画するコード
<!DOCTYPE HTML>
<html>
    <head>
	    <title>Line Example</title>
        <style>
            body {
                margin: 0px;
                padding: 0px;
            }
            
            #myCanvas {
                border: 1px solid #9C9898;
            }
        </style>
        <script>
            
          window.onload = function() {
                var canvas = document.getElementById("myCanvas");
                var context = canvas.getContext("2d");
                
                // blue line with round ends
                context.beginPath();
                context.moveTo(50, 50);
                context.lineTo(300,50);
                context.lineWidth = 10;
                context.strokeStyle = "#0000FF"; 
                context.lineCap = "round";
                context.stroke();

                // green line with square ends
                context.beginPath();
                context.moveTo(50, 100);
                context.lineTo(300,100);
                context.lineWidth = 20;
                context.strokeStyle = "#00FF00"; 
                context.lineCap = "square";
                context.stroke();

                // purple line with butt ends
                context.beginPath();
                context.moveTo(50, 150);
                context.lineTo(300, 150);
                context.lineWidth = 30;
                context.strokeStyle = "#FF00FF"; 
                context.lineCap = "butt";
                context.stroke();
            };
        </script>
    </head>
    <body>
        <canvas id="myCanvas" width="400" height="200">
        </canvas>

    </body>
</html>

矩形を描画する

キャンバスに矩形の領域を描画するには、以下の 3 つのメソッドがあります。

  • fillRect(x,y,width,height): 矩形を塗りつぶして描画します。
  • strokeRect(x,y,width,height): 矩形の輪郭を描画します。
  • clearRect(x,y,width,height): 指定の領域をクリアして、完全に透明にします。

上記のメソッドでは、いずれも Canvas の左上隅 (x=0, y=0) を基準とした矩形の相対位置を xy で指定し、widthheight で矩形の幅と高さを指定します。

図 3 に、リスト 2 のコードで作成された 3 つの矩形領域を示します。

図 3. キャンバスに描画された矩形の領域
黄色で塗りつぶされたボックスのなかに、太い線の黒い正方形と細い線の四角形が示されています。

fillRect() メソッドは、デフォルトの黒で塗りつぶした矩形を描画します。clearRect() メソッドは、この最初に fillRect() メソッドで描画した矩形の中央の矩形領域をクリアします。strokeRect() メソッドが描画する矩形には、可視の黒い境界線しかありません。

リスト 2. キャンバスに矩形を描画するコード
<!DOCTYPE HTML>
<html>
<head>
<title>Rectangle Example</title>
        <style>
            body {
                margin: 0px;
                padding: 0px;
            }
            
            #myCanvas {
                border: 1px solid #000000;
                background-color: #ffff00;
            }
        </style>
<script type="text/javascript">
function drawShape(){
   var canvas = document.getElementById('myCanvas');

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


    context.fillRect(25,25,50,50);
    context.clearRect(35,35,30,30);
    context.strokeRect(100,100,50,50);

}
</script>
</head>
<body onload="drawShape();">
   <canvas id="myCanvas" width="200" height="200"></canvas>
</body>
</html>

弧、曲線、円、半円を描画する

円と半円には、どちらも arc() メソッドを使用します。以下に示されているように、arc() メソッドは 6 つの引数を取ります。

context.arc(centerX, centerY, radius, startingAngle, endingAngle, antiClockwise);

引数 centerX および centerY は、円の中心座標です。radius は数学で言う、円の中心から円周までの直線距離に相当します。このメソッドによって描画される弧は、指定された円の一部になります。弧の始点と終点は、それぞれ引数 startAngleendAngle (ラジアン単位) で指定します。anticlockwise 引数はブール値で、値が true の場合には弧が反時計回りで描画され、false の場合には時計回りで描画されます。

arc() メソッドを使用して円を描画するには、開始角度を 0 に定義し、終了角度を 2*PI に定義します (以下を参照)。

context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);

arc() メソッドで半円を描画する場合は、終了角度を startingAngle + PI に定義します (以下を参照)。

context.arc(centerX, centerY, radius, startingAngle, startingAngle + Math.PI, false);

二次曲線

二次曲線を描画するには、以下に示す quadraticCurveTo() メソッドを使用します。二次曲線は、コンテキストでの始点、制御点、および終点によって定義されます。線の曲率は、制御点によって決まります。

context.moveTo(x, y);
context.quadraticCurveTo(controlX, controlY, endX, endY);

ベジェ曲線

二次曲線と同じく、ベジェ曲線にも始点と終点がありますが、二次曲線と異なる点は、ベジェ曲線には 2 つの制御点があることです。

context.moveTo(x, y);
context.bezierCurveTo(controlX1, controlY1, controlX2, controlY2, endX, endY);

ベジェ曲線を描画するには、bezierCurveTo() メソッドを使用します。ベジェ曲線の定義には、制御点が 1 つだけではなく、2 つ使用されるので、より複雑な湾曲を描くことができます。

図 4 に、(左から右に向かって) 弧、二次曲線、ベジェ曲線、半円、円を示します。

図 4. 弧、曲線、円
キャンバス上の弧、曲線、円、半円を示す画像

リスト 3 に、図 4 を描画するために使用したコードを記載します。

リスト 3. 弧、曲線、円のコード
<!DOCTYPE HTML>
<html>
    <head>
	<title>Arcs, Curves, Circles, & Semicircles</title>
        <style>
            body {
                margin: 0px;
                padding: 0px;
            }
            
            #myCanvas {
                border: 1px solid #9C9898;
            }
        </style>
<script>
function drawArc(){
    var canvas = document.getElementById("myCanvas");
    var context = canvas.getContext("2d");
 
    var centerX = 100;
    var centerY = 160;
    var radius = 75;
    var startingAngle = 1.1 * Math.PI;
    var endingAngle = 1.9 * Math.PI;
    var counterclockwise = false;
 
    context.arc(centerX, centerY, radius, startingAngle, 
        endingAngle, counterclockwise);
 
    context.lineWidth = 10;
    context.strokeStyle = "black"; 
    context.stroke();
};

function drawQuadratic(){
    var canvas = document.getElementById("myCanvas");
    var context = canvas.getContext("2d");
 
    context.moveTo(200, 150);
 
    var controlX = 288;
    var controlY = 0;
    var endX = 388;
    var endY = 150;
 
    context.quadraticCurveTo(controlX, controlY, endX, endY);
    context.lineWidth = 10;
    context.strokeStyle = "black"; 
    context.stroke();
};

function drawBezier(){
    var canvas = document.getElementById("myCanvas");
    var context = canvas.getContext("2d");
 
    context.moveTo(350, 350);
 
    var controlX1 = 440;
    var controlY1 = 10;
    var controlX2 = 550;
    var controlY2 = 10;
    var endX = 500;
    var endY = 150;
 
    context.bezierCurveTo(controlX1, controlY1, controlX2, 
        controlY2, endX, endY);
 
    context.lineWidth = 10;
    context.strokeStyle = "black"; 
    context.stroke();
};

function drawCircle(){
    var canvas = document.getElementById("myCanvas");
    var context = canvas.getContext("2d");
 
    var centerX = 450;
    var centerY = 375;
    var radius = 70;
 
    context.beginPath();
    context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
 
    context.fillStyle = "#800000";
    context.fill();
    context.lineWidth = 5;
    context.strokeStyle = "black";
    context.stroke();
};


function drawSemicircle(){
    var canvas = document.getElementById("myCanvas");
    var context = canvas.getContext("2d");
 
    var centerX = 100;
    var centerY = 375;
    var radius = 70;
    var lineWidth = 5;
 
    context.beginPath();
    context.arc(centerX, centerY, radius, 0, Math.PI, false);
    context.closePath();
 
    context.lineWidth = lineWidth;
    context.fillStyle = "#900000";
    context.fill();
    context.strokeStyle = "black";
    context.stroke();
};

window.onload = function (){
drawArc();
drawQuadratic(); 
drawBezier(); 
drawCircle(); 
drawSemicircle()
}
</script>
    </head>
    <body>
        <canvas id="myCanvas" width="600" height="500">
        </canvas>
    </body>
</html>

変形: 移動、伸縮、回転

translate()scale()rotate() はいずれも、現行のマトリックスを変更するメソッドです。translate(x, y) メソッドは、キャンバス上のアイテムを、グリッド上の異なる点に移動します。translate(x,y) メソッドの (x,y) 座標は、画像を x 方向に移動するピクセル数、y 方向に移動するピクセル数を指定します。

例えば、drawImage() メソッドを使って (15,25) の位置に画像を描画するとします。この場合、引数 (20,30) を指定して translate() メソッドを実行すれば、その画像を (15+20, 25+30) = (35, 55) の位置に移動することができます。

scale(x,y) は、画像のサイズを変更するメソッドです。引数 x が水平方向の伸縮係数を指定し、引数 y が垂直方向の伸縮係数を指定します。例えば、scale(1.5, .75) を指定すると、画像は x 方向に 50% 拡大される一方、y 方向では現行サイズの 75% に縮小されます。rotate(angle) は、指定された角度に従ってオブジェクトを回転させるメソッドです。

図 5 は、translate()scale()、および rotate() メソッドを使用して実現できるレンダリングの一例です。

図 5. 変形を使用する
mirror image という単語を左右に反転して表示する青いボックスの画像

リスト 4 に、図 5 の画像を描画するコードを記載します。

リスト 4. 変形した画像を描画するコード
<!DOCTYPE HTML>
<html>
<head>
<Title>Transformations Example</title>
<script>
 
window.onload = function() {
	var canvas=document.getElementById("myCanvas");
	var context=canvas.getContext("2d");
 
	var rectWidth = 250;
	var rectHeight = 75;
 
	// translate context to center of canvas
	context.translate(canvas.width/2,canvas.height/2); 		
 
	// half the y component 
	context.scale(1,0.5);

	// rotate 45 degrees clockwise
	context.rotate(-Math.PI/4); 
 
	context.fillStyle="blue";
	context.fillRect(-rectWidth/2,-rectHeight/2,
		rectWidth,rectHeight);


	// flip context horizontally
	context.scale(-1,1);
 
	context.font="30pt Calibri";
	context.textAlign="center";
	context.fillStyle="#ffffff";
	context.fillText("Mirror Image",3,10);

}
 
</script>
</head>
<body>
	<canvas id="myCanvas" width="400" height="400"></canvas>
</body>
</html>

グラデーション

グラデーションとは色を混ぜながら、ある色から別の色へと変化させていく塗りつぶしのことです。キャンバスで描画できるグラデーションのタイプには、線形グラデーションと円形グラデーションがあります。

線形グラデーションを描画するには、createLinearGradient() メソッドを使用します。createLinearGradient(x0,y0,x1,y1) は、(x0,y0)(x1,y1) で指定されるグラデーションの開始点と終了点を結ぶ直線に沿って、グラデーションを描画します。このメソッドは、オブジェクトを返します。

カラー・グラデーションでは、さまざまな色を使用することができます。addcolorStop(offset, color) メソッドは、指定されたオフセット位置で、グラデーションに指定した特定の色が終了することを指定します。addColorStop() メソッドでは、0 から 1 までの範囲でオフセットを指定することができます。この指定したオフセットから、次の色への遷移が開始されます。オフセットの値 0 は、グラデーションの始点で、値 1 はオフセットの終点です。カラー・グラデーションを定義した後は、グラデーション・オブジェクトを fillStyle() に割り当てることができます。さらに、fillText() メソッドを使用して、グラデーションを付けたテキストを描画することもできます。

円形グラデーションを作成する createradialGradient(x0,y0,r0,x1,y1,r1) は、以下の 6 つの引数を使用して、複数の色を円形 (円錐形) パターンで組み合わせます。

  • (x0,y0): 円錐形の最初の円の中心。
  • r0: 最初の円の半径。
  • (x1,y1): 円錐形の 2 番目の円の中心。
  • r1: 2 番目の円の半径。

図 6 に、線形グラデーション、テキスト・グラデーション、傾けた線形グラデーション、そして円形グラデーションを示します。

図 6. グラデーションの例
キャンバスに描画されたグラデーション

リスト 5 に、図 6 を作成するために使用したコードを記載します。

リスト 5. グラデーションのサンプル・コード
<!doctype>
<html>
<head>
<title>Gradient Example</title>
<script>
   window.onload = function() {
      var canvas = document.getElementById("myCanvas");

      var context = canvas.getContext("2d");

      //Let's try the gradient on a rectangle

      // Create a linear gradient 
      var fillColor = context.createLinearGradient(50,50, 150,50);

      // Set  gradient colors
      fillColor.addColorStop(0.15,"red");
      fillColor.addColorStop(0.35,"black");
      fillColor.addColorStop(0.65,"green");
      fillColor.addColorStop(0.87,"yellow");

      // Assign gradient object to fillstyle
      context.fillStyle= fillColor;

      // Draw rectangle
      context.fillRect(50,50,100,100);

      // With text  

      var fillColorText = context.createLinearGradient(300,50,600,50);
 
      fillColorText.addColorStop(0.2,"red");
      fillColorText.addColorStop(0.4,"black");
      fillColorText.addColorStop(0.6,"green");
      fillColorText.addColorStop(0.8,"yellow");


     context.fillStyle= fillColorText;

      context.font="40px verdana";
      context.textBaseline="top";
      context.fillText("With text too!", 300,50)

      // Gradient on a diagonal
      var fillColordiagonal = context.createLinearGradient(50,200, 100,450);

      // Gradient colors
      fillColordiagonal.addColorStop(0.2,"red");
      fillColordiagonal.addColorStop(0.4,"black");
      fillColordiagonal.addColorStop(0.6,"green");
      fillColordiagonal.addColorStop(0.75,"yellow");

      // Assign gradient object to fillstyle
      context.fillStyle= fillColordiagonal;

      // Draw  rectangle
      context.fillRect(50,225, 100,250);

      // Draw radial gradient
     fillColorRadial = context.createRadialGradient(450,300,0, 450,300,200);
     fillColorRadial.addColorStop(0, "red");
     fillColorRadial.addColorStop(0.2, "black");
     fillColorRadial.addColorStop(0.4, "green");
     fillColorRadial.addColorStop(0.7, "yellow");
     context.fillStyle = fillColorRadial;
     context.rect(300,200,500,400);
     context.fill();

}
</script>
</head>
<body>
<div>
    <p><canvas id="myCanvas" width="600" height="400"></canvas></p>
</div>
</body>
</html>

画像のトリミング

画像から選択した領域をトリミングすることによって、画像を変更することができます。キャンバス上でのトリミングは、drawImage() メソッドをオーバーロードする機能です。drawImage() メソッドには 3 種類の選択肢があり、3 つ、5 つ、または 9 つの引数を使用することができます。

3 つの引数からなる構成 (drawImage(image, dx, dy)) では、キャンバス上の宛先座標 (dx, dy) で画像が描画されます。この座標が、画像の左上隅の位置になります。

5 つの引数からなる構成 (drawImage(image, dx, dy, dw, dh)) では、宛先の幅と高さが指定されます。画像は、宛先の幅と高さに合わせて伸縮されます。

9 つの引数からなる構成 (drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh)) では、画像を取得し、ソース (sx,sy) 座標で始まる矩形領域を (sw,sh) で指定された幅と高さで切り取り、切り取った領域を宛先の幅と高さ (dw,dh) に合わせて伸縮して、キャンバスの (dx,dy) の位置に配置します。

図 7 に、トリミング前の画像を示します。

図 7. 画像をトリミングする
馬にまたがるナポレオンの肖像画

図 7 に示した画像を元に、これからいくつかの画像をキャンバス上に配置します。最初の画像は、キャンバスと同じサイズの背景として使用されます。2 つ目の画像は、ひと回り小さいサイズでキャンバスの右下隅に挿入されます。3 つ目の画像は、ナポレオンの頭部だけを切り取った画像で、キャンバスの左上隅に配置されます。トリミングされた最終的な画像を図 8 に示します。

図 8. トリミング後の画像
同じナポレオンの画像ですが、左上には頭部だけの画像、右下には縮小版の画像が表示されています。

リスト 6 に、図 8 を作成するために使用したコードを記載します。このコードを実行するには、その前に必ず、サンプル画像の Napolean.png をダウンロードしてください。

リスト 6. サンプル画像をトリミングするコード
<!doctype>
<html>
<head>
<title>Crop Example</title>
<script type="text/javascript">
  window.onload = function()  {
  var canvas=document.getElementById("cropNapolean");
	var context=canvas.getContext("2d");
 
	var imageObj = new Image();
	imageObj.onload = function() {
	// draw image to cover the entire canvas
		context.drawImage(imageObj,0,0, 600, 400);
 
	// draw small image in bottom right corner
		var sourceX = 0;
		var sourceY = 0;
		var sourceWidth = 1200;
		var sourceHeight = 801;
		var destX = 300;
		var destY = 200;
		var destWidth = sourceWidth - 900;
		var destHeight = sourceHeight - 600;
 
		context.drawImage(imageObj, sourceX, sourceY, sourceWidth,
			sourceHeight, destX, destY, destWidth, destHeight);
	
	 //draw Napolean's head only
		var sourceNapoleanX = 460;
		var sourceNapoleanY = 25;
		var sourceNapoleanWidth = 250;
		var sourceNapoleanHeight = 175;
		var destNapoleanX = 0;
		var destNapoleanY = 0;
		var destNapoleanWidth = sourceNapoleanWidth - 150 ;
		var destNapoleanHeight = sourceNapoleanHeight - 100;
 
        context.drawImage(imageObj, sourceNapoleanX, sourceNapoleanY, 
             sourceNapoleanWidth, sourceNapoleanHeight, 
               destNapoleanX, destNapoleanY, 
                 destNapoleanWidth, destNapoleanHeight);
	}
	imageObj.src = "Napoleon.png";	
}
</script>
  
  </head>
<body>
  <div>
    <p><canvas id="cropNapolean" width="600" height="400"></canvas></p>
  </div>
</body>
</html>

アニメーションと複数のキャンバス

アニメーションを処理するときには、常にレイヤーの問題が持ち上がってきます。レイヤーを使用することで、簡単かつ効率的にコーディングとデバッグを行えるように、コンポーネントを分離できるためです。Canvas API にはレイヤーがありませんが、代わりに複数のキャンバスを作成することができます。

アニメーションは時間の経過に合わせて制御しなければなりません。したがって、アニメーションを作成するには、アニメーションの各フレームに対処する必要があります。Canvas API にはアニメーションに関して、1 つの重大な制約があります。それは、形状がキャンバスに描画された後、その形状はそのままの状態で維持されることです。そのため、形状を動かすには、その形状を再描画する必要があります。

アニメーションを作成する方法は以下のとおりです。

  1. 以前に描画されたすべての形状をキャンバスからクリアします。
  2. キャンバスの状態を保存して、フレームが描画されるたびに元の状態が使用されるようにします。
  3. フレームをレンダリングするステップを実行します。
  4. 状態を保存した場合は、新しいフレームを描画する前に、その状態に戻します。

アニメーションは 2 通りの方法で制御することができます。それは、setInterval 関数を使用する方法と setTimeout 関数を使用する方法です。いずれも、設定した期間内に関数を呼び出すために使用することができます。setInterval 関数は、指定されたコードを繰り返し実行します。setTimeout 関数は、指定された時間が経過した後に 1 度だけ実行されます。

図 9 に、複数のキャンバスで作成したスイマーのアニメーションを構成する 1 つのフレームを示します。水はある 1 つのキャンバス上にあり、スイマーは別のキャンバス上にあります。

図 9. 複数のキャンバス上の画像を使用したアニメーション
青のグラデーションの背景に描画された棒線画

スイマーのアニメーションには、リスト 7 のコードを使用します。水を描画するには線形グラデーションを使用します。4 つの青の色調を使うことで、水のように見せています。スイマーの動きを表現するには、positionXpositionY の値を使用してスイマーの画像の姿を変更します。スイマーの頭は、arc() メソッドで作成します。スイマーの脚と腕を描画するには、線を描画した後、線の lineTo() によって位置を変更します。そして moveTo() によって位置を変更して、胴体を動かします。これはアニメーションであるため、スイマーがどのように動くかを見るには、このコードを実行する必要があります。

リスト 7. アニメーションのサンプル・コード
<!DOCTYPE HTML>
<html>
    <head>
	<title>Animation & Multiple Canvas Example</title>
<script>            
// Water canvas
function  drawWater() {
    var canvasWater = document.getElementById("myWaterCanvas");
    var contextWater = canvasWater.getContext("2d");
	contextWater.globalAlpha = .50 ;

    // Create a linear gradient fill
    var linearGrad = contextWater.createLinearGradient(0,0,400,400);
    linearGrad.addColorStop(0, '#0000ff'); // sets the first color
    linearGrad.addColorStop(.25, '#0099ff'); // sets the second color
    linearGrad.addColorStop(.50, '#00ccff'); // sets the third color
    linearGrad.addColorStop(.75, '#00ffff'); // sets the fourth color
    contextWater.fillStyle = linearGrad;
    contextWater.fillRect(0,0,400,400);
}

// Swimmer canvas
           setInterval(drawSwimmer, 30);
           var positionX = 0;
           var positionY = 0;
            
          function  drawSwimmer(){
                var canvasSwimmer = document.getElementById("mySwimmerCanvas");
                var contextSwimmer = canvasSwimmer.getContext("2d");
                contextSwimmer.clearRect(0,0,400,400);

                if (positionX < 30)
                  {
                     positionX += 1;
                     positionY += 1;
                  }
                else
                {
                     positionX = 0;
                     positionY = 0;
                }
               

                contextSwimmer.save();

               // draw circle for head
               var centerX = 200;
               var centerY = 50;
               var radius = 20;
 
               contextSwimmer.beginPath();
               contextSwimmer.arc(centerX, centerY+positionY, 
			                         radius, 0, 2 * Math.PI, false);
 
               contextSwimmer.fillStyle = "#000000";
               contextSwimmer.fill();
               contextSwimmer.lineWidth = 5;


                // torso
                contextSwimmer.beginPath();
                contextSwimmer.moveTo(200,70+positionY);
                contextSwimmer.lineTo(200,175);
                contextSwimmer.lineWidth = 10;
                contextSwimmer.strokeStyle = "#000000"; 
                contextSwimmer.lineCap = "round";
                contextSwimmer.stroke();

               // image right arm
                contextSwimmer.beginPath();
                contextSwimmer.moveTo(200, 100);
                contextSwimmer.lineTo(175-positionX,140-positionY);
                contextSwimmer.lineWidth = 10;
                contextSwimmer.strokeStyle = "#000000"; 
                contextSwimmer.lineCap = "round";
                contextSwimmer.stroke();

               // image left arm
                contextSwimmer.beginPath();
                contextSwimmer.moveTo(200, 100);
                contextSwimmer.lineTo(225+positionX,140-positionY);
                contextSwimmer.lineWidth = 10;
                contextSwimmer.strokeStyle = "#000000"; 
                contextSwimmer.lineCap = "round";
                contextSwimmer.stroke();

               // image right leg
                contextSwimmer.beginPath();
                contextSwimmer.moveTo(200, 175);
                contextSwimmer.lineTo(190-positionX,250-positionY);
                contextSwimmer.lineWidth = 10;
                contextSwimmer.strokeStyle = "#000000"; 
                contextSwimmer.lineCap = "round";
                contextSwimmer.stroke();


               // image left leg
                contextSwimmer.beginPath();
                contextSwimmer.moveTo(200, 175);
                contextSwimmer.lineTo(210+positionX,250-positionY);
                contextSwimmer.lineWidth = 10;
                contextSwimmer.strokeStyle = "#000000"; 
                contextSwimmer.lineCap = "round";
                contextSwimmer.stroke();

                contextSwimmer.restore();

           };

</script>

</head>
    <body onload="drawWater();">
        <canvas id="myWaterCanvas" width="400" height="400" style="z-index: 2; 
		              position:absolute;left:0px;top:0px;">
        </canvas>
        <canvas id="mySwimmerCanvas" width="400" height="400" style="z-index: 1; 
		              position:absolute;left:0px;top:0px;">
        </canvas>

    </body>
</html>

まとめ

HTML5 の Canvas は、ブラウザー・ベースの RIA を作成する上で中心的な役割を果たします。Canvas は、JavaScript と皆さんの想像力によって実現する実用的な描画環境です。Canvas について習得するのはそれほど難しいことではありません。さらに、Web 上にはトレーニングや学習のニーズに応えてくれる、チート・シートやブログ、オンライン記事、動画によるチュートリアル、動画以外の方法によるチュートリアル、そしてサンプル・アプリケーションなど、多数のサポート・ツールもあります。

テキストと画像を視覚的に変更し、動きをシミュレートできる機能を備えた Canvas は、極めて貴重なツールです。デザイナーまたは開発者のどちらの視点から Canvas に取り組むかによらず、モバイル機器上で動作するゲーム・アプリケーションを構築する場合や、ただ単に画面全体の表示域をより有効に使用したいという場合でも、Canvas を使ってください。Canvas は HTML5 のエクスペリエンスを実現するには欠かせないコンポーネントです。


ダウンロード

内容ファイル名サイズ
Napoleon imageNapoleon.zip2045KB

参考文献

学ぶために

製品や技術を入手するために

  • オープンソースのモジュール式 JavaScript ライブラリー、Dojo Toolkit は、特定のプラットフォームに依存しない JavaScript/Ajax ベースのアプリケーションおよび Web サイトを素早く開発するのに役立ちます。
  • IBM のソフトウェアを無料で試してみてください。評価版をダウンロードすることも、オンライン評価版にログインすることも、Sandbox 環境で製品を操作することも、クラウドを介して IBM 製品にアクセスすることもできます。選べる IBM 製品の評価版は 100 を超えています。

議論するために

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Web development
ArticleID=749777
ArticleTitle=HTML5 の基礎: 第 4 回 最後の仕上げ
publish-date=08052011