演習3 - canvasへの描画の初歩(javascriptの導入)

3.0 はじめに

 本演習から、HTML文書の中にいよいよjavascriptの機能を導入していきます。 今後、この講義は半期を通じて、javascriptの使い方にある程度まで習熟することを目標としていきます。 実は、これまでに学んできたHTML言語の中のタグや要素といった構造 (あるいはCSSという機能)に関する知識は、 HTML文書以外ではあまり応用が利きません。 逆に、これから学ぶjavascriptは、他の多くの主要な言語(C, C++, Java, php, processing...)と 共通の機能や構造を共有しており、 javascriptを使いこなせるようになれば比較的簡単に他の言語の学習に移行することができます。 すなわち、1年生の間に、javascriptの使い方に習熟することは、 2年生以降でJavaやprocessingを学習していくための貴重な足固めとなります。 逆に、ここで出遅れてしまうと、2年生以降のプログラミングの授業についていけなくなってしまうおそれがありますので強い意識を持って授業にのぞむことが大事です。

 なお、通常、javascriptはHTML文書の中に埋め込まれるようなかたちで利用されます。 これからの授業でも、HTMLに対して描画の機能を拡張的に加えるためにjavascriptの記述を利用します。 よって、当然ながら、HTMLの構造(要素、属性)とjavascriptはお互いに連携し合うことが必要となります。 そのため、これまでに学んできたHTMLやCSSの(最低限の)知識についても忘れないようにしてください。

 javascriptの講義に入る前にもう一点。 これからの講義では、(特にはじめのうちは)「習うより慣れろ」ということで、 とにかく手を動かしてもらうことを重視します。 構文などの説明をあえて後回しにすることもありますので、 はじめはよく意味がよくわからずに不安を抱えたまま演習にとりかかることも多いかと思います。 講義が進むにつれて、徐々に細かい説明も加えていきますが、 まずは自分の手でプログラミングしてアウトプットが変化することを実感してみてください。 誰でもそうですが、辛抱強く演習を続けていれば、 徐々に全体の輪郭がクリアに見えるようになるはずです。


 では、はじめましょう。

3.1 HTMLのcanvas要素

 まずは、HTML5において初めて導入された、描画領域を生成する要素であるcanvas要素について紹介します。今後の授業で扱うサンプルの土台となるものです。

サンプル

- - - - - ソース - - - - - - - - - - - - - - - - - - - - -

(sample3A.html)

- - - - - 実行結果 - - - - - - - - - - - - - - - - - - - -

(sample3A.html)

Drawing

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

canvas要素の記述方法

 サンプルのソースを確認します。body要素の中には、 ただ一つのcanvas要素が記述されています(12行目)。 canvas要素は、名前から推測される通り、描画をするための空間に対応します。 この描画空間のサイズは、canvas要素の属性であるwidthとheightにより設定されています。 サンプルではcanvasの属性として、識別子(id=main)と幅(width=160)と高さ(height=120)が設定されていますので、結果として、160x120の描画空間が生成されます。描画空間は、CSSによって細い実践で囲まれているため、描画空間の外観を実際に確認することができます。

 一方で、最も重要な、この描画空間に「何を書くか」に関する命令は、canvas要素の属性としては記述することができません。この部分は、HTML文書内に埋め込まれたjavascriptの中で記述することになっています。すなわち、HTMLのcanvas要素は、はじめからjavascriptとの連携を前提として存在しているのです。 後で明らかになりますが、canvas要素の識別子(main)は、javascriptによって「参照される」ために必要となるものであり、一種のアドレスのようなものです。

3.2 javascriptによる描画命令の記述


 それでは、これからcanvas要素の描画領域に実際に描画してみます。 まずは、サンプルからです。

サンプル

- - - - - ソース - - - - - - - - - - - - - - - - - - - - -

(sample3B.html)

- - - - - 実行結果 - - - - - - - - - - - - - - - - - - - -

(枠線内をクリックすると表示されます。)

(sample3B.html)

Drawing

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

サンプルの解説

 実行結果を開くと、canvas領域内に四角形が描かれていることがわかります。 それでは、描画と関係する部分について簡単に確認していきましょう。 まず、sample3B.htmlには、head要素の中に新たにscript要素が埋め込まれていることがわかります。 CSSをstyle要素の中に記述したように、javascriptはこのscript要素の中に記述することになっています。 それでは、あらためて、script要素内の記述を以下に書き下してみます (''javascriptにおいて「//」から行末までの文はコメント文と呼ばれ、 プログラム実行時には無視されます'')。

 以下で、非常におおざっぱに、script要素の内容を把握してみます。


function draw(){...}
  • drawという名前の命令をつくります。
  • 命令の内容は波括弧内に書いてあります。
  var canvas = document.getElementById("main");
  var context = canvas.getContext("2d");
  • idがmainであるcanvas要素から描画領域contextを取得します。
  • contextは、様々な描画命令を受け付けるための受け皿となります。 描画における、このような機能を持ったものをコンテキストと呼びます。
  • 以上の2つの行は、canvas要素に描画するにあたって、 おまじないのように記述する必要があります(ただしid名は変える)。
  context.strokeStyle = "red";
  context.strokeRect(25,25,50,90);
  • canvasの描画領域に、四角形の境界線を赤色で描画します。

どうですか。初心者にとっては、一気に覚えるべきことが増えて混乱しているかもしれませんが、今日の段階では完全に理解する必要は全くありません。大雑把に以下のような処理の流れを汲んでもらえれば十分です。

  1. drawという名前の命令を定義し、
  2. canvas要素の識別子がmainである描画領域のコンテキストを取得し、
  3. 描画領域のコンテキスト(context)に対して描画命令を出す。

なお、1で命令の名前を決めていますが、これはどこで参照される必要があるのでしょうか。

<body onLoad="draw()">

sample3B.htmlの20行目に上のような文が見られます。 ここではbody要素にonLoad属性が定義されており、ここでdraw()が紐づけられています。 この文は、body要素がロードされた(読み出された)時に、drawという名前の命令を実行せよということを意味しています。 これによって、HTMLが読み出されたときに自動的にdrawが実行され、mainという識別子を持つcanvas要素の描画領域に(今回の場合は)四角形の枠線が描画されたわけです。

3.3 プロパティーとメソッド

プロパティー

 以下では、具体的な描画命令の構文に焦点を当てていきましょう。 実際の描画に対応した箇所は、10-11行の2行となります。まず、10行目から見てみます。

context.strokeStyle = "red";

ここでは、描画領域コンテキストであるcontextに対して、線の色を赤とするように設定しています。一般に、

A.B = XXX;

という構文は、 「Aという対象が有しているBという属性に対して、XXXを設定せよ」ということを意味しています (XXXには数字や文字など)。 AとBの関係は、HTMLにおける要素と属性との関係と同じです。 javascriptではAをオブジェクト、Bをプロパティーと呼びます *1。 Bとしてどのようなプロパティーが使えるかは、Aであるオブジェクトの種類に依存します。

メソッド、引数

 次に11行目を見ていきます。

context.strokeRect(25,25,50,90);

この一文によって、コンテキストに対して四角形の枠線の描画を命令しています。 ここでは、もう少し詳しく命令の中身を追ってみましょう。 strokeRectに続いて4つの数字が記されています。 これらの数字は、それぞれ以下の数値に対応しています。

コンテキスト.strokeRect(x,y,w,h);
x
四角形の左上の頂点のx座標(ピクセル)
y
四角形の左上の頂点のy座標(ピクセル)
w
四角形の横幅(ピクセル)
h
四角形の高さ(ピクセル)

ここで想定されているxy座標系は、皆さんがこれまで数学で勉強してきたものとは違い、canvas領域の左上の頂点を原点として、右にx方向、下にy方向と進行します。以下の図で確認しておいてください。

canvas_axis.png

このように、プログラムの世界では、常に左上が原点となることに注意してください(普通、画面をドラッグエンロールで拡大縮小する時に左上は動かしませんよね)。確認のため、strokeRectの中の4つの数字を適当に変えて、異なる四角形の枠線ができることを確認してみてください(sample3B.htmlをコピーして、数字の部分だけを変えてみてください。)。

 一般に、

A.B(p,q,...);

という構文は、「オブジェクトAに対して、Bという命令を実行せよ。」ということを意味します。 このとき、Bをメソッドと呼びます。 プロパティーと同様ですが、 オブジェクトの種類によってどのメソッドが使えるかはあらかじめ決まっています。 また、(p,q,...)の部分を引数と呼び、メソッドを実行するにあたって補助的な情報を与えます。 今回の場合、contextがオブジェクトに、strokeRectがメソッドに、(25,25,50,90)が引数に対応します。 引数の数や種類は、メソッドの種類に依存します。また、同じメソッドで複数の引数の組が使われることもあります。引数が存在しない場合、以下のような記述となります。

A.B();

 実は、6行目で描画命令の名前を定義するために記したdraw()が、まさにこの「引数の存在しないメソッド」に該当します。今回、drawという命令として四角形の枠線描画を設計したように、メソッドは、われわれ自身の手で好きなようにプログラムすることもできます。オブジェクトやメソッドについては、まだまだ学ぶべきことがありますが、いまは時期尚早です。ここでは、以上で述べたような非常に簡単な理解にとどめておきます。

3.4 その他の描画メソッド

 コンテキストオブジェクトに対して可能な描画命令はもちろん、先ほどの例だけではありません。以下では、代表的な描画方法について学習し、メソッドやプロパティーの使い方に慣れていきましょう。

線の太さ、塗りつぶし

 まずはサンプルと実行結果を確認してください。

- - - - - ソース - - - - - - - - - - - - - - - - - - - - -

(sample3C.htmlのscript要素)

- - - - - 実行結果 - - - - - - - - - - - - - - - - - - - -

(枠線内をクリックすると表示されます。)

(sample3C.html)

Drawing

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

 今回は新たに二つのプロパティー(lineWidthとfillStyle)と1つのメソッド(fillRect)が使われています。 名前から連想されるように、lineWidthは輪郭線の太さを、fillStyleは塗りつぶす際の色を表します。 また、fillRectは四角形の内部を塗りつぶします。このときの色が、fillStyleによって決定されるということです。

パスによる描画

 ここでは、パスの概念を使って描画する方法を学びます。パスは、ここでは「線や曲線とそれらを結ぶ中継点の集まり」ぐらいに考えておいてください(illustratorを使う人には直感的に理解しやすいはずです)。まずはサンプルと実行結果を確認してください。

- - - - - ソース - - - - - - - - - - - - - - - - - - - - -

(sample3D.htmlのscript要素)

- - - - - 実行結果 - - - - - - - - - - - - - - - - - - - -

(枠線内をクリックすると表示されます。)

(sample3D.html)

Drawing

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

 以下で順を追って、サンプルの内容を説明します。 beginPath()は、「ここから(新しい)パスを開始しますよ」という合図です(14行目)。 moveTo(x,y)はペン先を(x,y)に置くイメージです(15行目)。 lineTo(x,y)によって、現在のペンの位置から(x,y)までの直線のパスが追加されていきます(16-17行目)。 19行目のmoveTo(250,50)によって、15-17行目までに結ばれていったパスは切られ、 新たに(250,50)がパスの開始点(始点)として設定されます。この新しいパスは、15-17行目で作られたパスとは区別されます。 このように、beginPath()でつくられたパスの中には、複数の(相互に区別できる)サブパスが含めることができます。 新しいサブパスに対して、lineToによって2本の直線パスが追加された後、closePath()によって現在のサブパスの開始点へと戻り、閉じられます。ここまでの段階で、二つのサブパスができていますが、ただパスがつくられただけで、実際には何も描画されていないことに注意してください(illustratorをイメージするとわかりやすいですね)。最終的に、stroke()によってパスの輪郭線が描画され(24行目)、fill()によってパスの塗りつぶしが行われます(25行目)。

パスによる描画の注意点

 パスを用いて描画をする際、 パスの作成と(moveTo, lineToなど)実際の描画(stroke()あるいはfill())は分離しています。 この際、描画において、どのパスまでが対象になっているかを把握することは非常に重要です。 これを理解するために、以下のサンプルを確認してみましょう。

- - - - - ソース - - - - - - - - - - - - - - - - - - - - -

(sample3E.htmlのscript要素)

- - - - - 実行結果 - - - - - - - - - - - - - - - - - - - -

(枠線内をクリックすると表示されます。)

(sample3E.html)

Drawing

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

 このサンプルでは、stroke()による輪郭線の描画が3回行われています(17, 22, 29行目)。それぞれのstroke()より前の部分では、それぞれ異なる輪郭線の描画色が設定されていますが(赤-14行目, 紫-19行目, 黄-26行目)、 実行結果を見ると、17行目で実行したはずの赤色のラインが紫色に置き換えられています。何故でしょう。

 stroke()は、現在のパスに登録されている全てのサブパスに対して輪郭線を描画せよという命令です(fill()についても同様)。よって、17行目の描画命令(赤)は、22行目の描画命令(紫)によって上塗りされてしまっているのです。これを避けるためには、24行目のようにbeginPath()を挿入します。beginPath()は、新しいパスの開始であるとともに、これまでに登録されてきた全てのサブパスをリセットする効果があります。これによって、stroke()やfill()によって描画するパスの対象を限定することができます。

3.5 演習課題

課題

 今回学んだ、四角形とパスを使って人の顔を書いてみてください。ファイル名はsample3X.htmlとします。

  • 丸(arc)は使わずに、直線と四角形のみを使うものとします。

3.6 リファレンス

四角形の描画方法

context.fillRect(x,y,w,h)
(x,y)を左上の頂点として幅w, 高さhの四角形を塗りつぶす
context.strokeRect(x,y,w,h)
四角形の輪郭線を書く
context.clearRect(x,y,w,h)
四角形の形に切り取る(該当部分を透明にする)

パスによる描画方法

  • パス
context.beginPath()
現在のパスをリセットする
context.moveTo(x,y)
新しいサブパスの開始点を(x,y)に定める
context.closePath()
パスの現在位置を現在のサブパスの開始点を結んでパスを閉じる
  • 直線
context.lineTo(x,y)
パスの現在位置と(x,y)を結ぶ直線のパスを追加する
  • 描画
context.fill()
現在の塗りつぶしスタイルで全てのサブパスを塗りつぶす
context.stroke()
現在の線スタイルでサブパスの輪郭線を描く
  • 色の指定("color"の記述は「色の記述方法」を参照)
context.fillStyle="color"
塗りつぶしの色の設定
context.strokeStyle="color"
線の色の設定

色の記述方法

"red", "blue", ...
色の直接の指定(カラーコード表を参照, http://www.colordic.org など)
"rgb(R,G,B)"
色のRGB成分を指定(0-255)
"rgba(R,G,B,alpha)"
色のRGB成分とアルファ値(半透明度, 0.0-1.0)の指定

*1 実際にはAはオブジェクトをさらに普遍化したクラスである場合も存在する。

添付ファイル: filecanvas_axis.png 330件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2013-10-22 (火) 17:22:02 (2063d)