前回、よ〜やく
画面にcube-600.htmlファイルの内容が表示されると、JavaScriptで書いたthreeStart関数が呼び出されて実行されるよ。
って話まで進んだわけですよ。
というわけで、今回はJavaScriptちゃんのお話。
まず、threeStart関数でやってることは何かっていうと
1)3D空間にカメラを配置し、その空間に展開される光景(シーン)として、光源、立方体、球体を配置する。
2)カメラから見た光景は、こんな感じですよ〜とWebブラウザの自分が担当する画面領域に表示する。
ことです。
このうち青色枠の処理は、表示中に繰り返し実行(秒間数十回)してます。
秒間数十回、画面を書き直すたびに少しづつ立方体の傾き大きくすることで、まるで本当に回転してるように見せかけてるわけです。アニメーションの基礎ですな。
そこらへんを念頭にthreeStart関数の手順を解説〜。
まず、関数は上から順に書かれている処理を実行することになっていて、threeStart関数では以下の4行が
canvas-frameという識別子から特定できるWebブラウザ上の2D平面を、3D空間を投影する領域として登録する。
という作業になってます。
じゃ、threeStart関数の先頭行は何かと言うと、こいつは処理の記述ではなく単なる覚書です。プログラム業界ではコメントと言います。
JavaScriptは // から改行までがコメントとみなされる仕組みで、文中のどこにでも入れることができます。
コメントは動作に何の影響も及ぼさない(読み込み時にWebブラウザがコメントか処理か判断する分くらいは影響する)んですが、後から見直した時に自分が何やろうとしてたか思い出すのに便利なのでよく使います。
コメントは動作には関係しない。
というのを覚えておきましょう。
なので、threeStart関数の場合、先頭から2つめの行からが処理ってことになるわけですよ。
最初にやってるのはcanvas-frameという識別子を持つ画面領域の特定。
記述中に出てくるdocumentという変数が、このJavaScriptを実行中のHTMLファイルの記述を抽象化した「何か」を指し示してます。
変数は、数学で使う変数とほぼ同じです。
違うところは、数学では変数を
x を 1とおくと、y = x + 1のyには何が入るか?
といったように、主に数を示す代用品として扱うのに対し、JavaScriptでは変数を、数だけじゃなく文字列や「何か」を示す代用品として扱います。
今回なら変数documentは
htmlというブロックにheadブロック、bodyブロックを持つ
bodyブロックにdivブロックを1つ持つ
このdivブロックはcanvas-frameという識別子を持ち縦横600ピクセルの領域
といった情報を持つ「何か」を示すわけです。
こういった抽象化された「何か」をJavaScriptではオブジェクトって言います。
で、documentの後ろに . でつながれたgetElementByIdは、オブジェクトに対する「指示」を意味していて
document.getElementById('canvas-frame')
はdocumentが示すオブジェクトに、getElementById('canvas-frame')という「指示」を送っていることになります。
これをJavaScriptではオブジェクトにメッセージを送ると表現します。
で、今回送ってるgetElementById('canvas-frame')というメッセージは
識別子canvas-frameを持つオブジェクトを取り出す
というもので、getElementByIdの後に続く('canvas-frame')が、識別子の指定となってます。JavaScriptではHTMLで指定した識別子を文字列として扱うんで ’ ’ で囲んで
’canvas-frame’
としてます。これが文字列を指定していますよという合図。ちなみに ” ” で囲んでも同じく文字列の扱いになります。
こんな感じで動作に対する付加情報が必要な場合は、メッセージ名の後ろに続く ( ) の間に、その情報を並べることになってます。
ちなみに、付加情報がない場合は () とだけ書きます。
この決まりは関数の呼び出しでも適用されて、前回のthreeStart関数の呼び出しでは特に渡すべき付加情報がないのでthreeStart()となっとるわけですね。
で、関数やメッセージは処理の結果を戻せるようにもなっていて、例えば数学なら
f(x) = x + 1
と定義された関数f(x)に対し
y = f(1)
と書いたなら、変数yは2と考えるのと同じように
frame = document.getElementById('canvas-frame')
というふうに = を使って結ぶことで、getElementById('canvas-frame')の処理結果が変数frameに設定されるようになってます。getElementById('canvas-frame')の処理結果とは
識別子canvas-frameを持つオブジェクト
なので、frameは識別子canvas-frameを持つオブジェクトを指し示すようになるわけです。
変数の名前は自由に決めてかまいません。frameが嫌ならcanvas_frameでもいいし、fとしてもいい。ただしcanvas-frameとは書けません。引き算と紛らわしい(canvas - frame)んで禁止されてます。
もうすでに使用しているdocumentを指定することも避けた方がいいでしょう。これはframeの手前にあるvarとも関係するスコープという仕組みに絡むことなんで後述。
あと、行の最後にある ; は処理と処理の間に入れる区切りです。JavaScriptの場合、改行も処理と処理の区切りと解釈されるんで、今回のような処理ごとに改行する書き方なら ; は無くても問題ないんですが
変わり者さんが処理と処理を連続で書こうとすると必須となります。
改行しろやヴオケエみたいな。
というわけで、今回の記述なら必要ないんですが、C言語のくせで ; 付けちゃってます。付けても問題は無っしんぐ。
で、次の処理はTHREE.WebGLRendererというオブジェクトの新規作成。新規にオブジェクトを作成する場合newキーワードをつけます。
renderer = new THREE.WebGLRenderer({antialias: true});
これでrendererって変数が、その作成したTHREE.WebGLRendererオブジェクトを示すようになります。
さっきのオブジェクトへのメッセージ送信と紛らわしんですが、こっちは
THREE.WebGLRenderer
がオブジェクトの種類を示してて、「THREE.WebGLRenderer」で1つの種類です。JavaScriptではオブジェクトの種類のことをクラスと呼びます。
今回ならTHREE.WebGLRendererというクラスのオブジェクトを作るってことになります。このオブジェクトが3D描画を担当するオブジェクトさんです。
作成時も、関数呼び出しやメッセージ送信と同じで、付加情報を ( ) で囲んで渡せます。今回渡してる
{antialias: true}
は連想配列と呼ばれるもので { } で囲んだ中に、キーと値のペアを書いて作ります。最初にキーを書いて : を挟んで値を書く。
必要なら , で区切って、複数のキーと値のペアを含ませることができるようになってもいます。
当然だけど、受け手側(今回ならTHREE.WebGLRendererを作る側)が知っているキーでないと意味をもちません。
ここではantialiasというキーにtrueを結びつけることで、作成されるTHREE.WebGLRendererオブジェクトに、3D描画時には時間が多少かかってもいいので、モニター上の文字や斜線などに生じるギザギザを目立たなくしてねとお願いしたことになります。こういったギザギザ除去処理をanti-aliasing(アンタイエリアシングとかアンチエリアシング)といいます。
指定している値は真偽値と呼ばれるもので、trueかfalseの2種類です。
true:真
false:偽
antialiasがtrue(真)だとanti-aliasingをするという意味になり、false(偽)だとanti-aliasingをしないという意味になります。違いに興味ある人はtrueのところをfalseに書き換えて読み込ませてみましょう。
その次の行の
renderer.setSize(frame.clientWidth, frame.clientHeight )
はrendererに対するsetSizeメッセージ送信です。
setSizeはTHREE.WebGLRendererオブジェクトに対して、3Dを表示する2D画面の大きさを指定するもんなんで、付加情報として2D画面の大きさが必要になります。
複数の付加情報は上記の連想配列を使う以外に、こんな感じに , で区切って渡す方法もある。付加情報に何をもらうかや、どういうもらい方をするかはTHREE.WebGLRendererが決めることで、こちら側は、その指定に従うだけです。今回なら、画面の横幅、高さを直接数値で
renderer.setSize(600, 600)
と書いてもいい。
ただ、これだとHTMLのCSSでcanvas-frameの大きさを、例えば100x100に変えても、THREE.WebGLRendererオブジェクト側は600x600のままってことになっちゃうんですよ。
それを避けるためにframe.clientWidthとframe.clientHeightと書いて、frameが示すオブジェクトに設定された横と縦の大きさを指定していることになります。
frame.clientWidthやframe.clientHeightは、どちらもframeに対するメッセージ送信に見えるけど、() がついてないのでメッセージ送信ではなく、オブジェクトの属性の値を意味します。
clientWidthが幅でclientHeightが高さの属性で、HTMLのCSSでcanvas-frameに指定したwidthとheightの値600、600が入ってます。
属性は、オブジェクトごとに保持される変数と考えてもらっていいです。JavaScriptでは属性のことをプロパティと呼びます。
なので、setSizeに渡される付加情報は、frameのプロパティclientWidthとclientHeightの値である600、600という数値ということになります。
ちなみにgetElementByIdが戻すオブジェクトのクラスはElementです。ここらへんはJavaScriptを学習しながら、おいおい調べればいいと思われ。
ここで↓
そして次の行でframeにappendChild(renderer.domElement)メッセージを送り、frameの子分として、rendererのdomElementプロパティが示すオブジェクトを加えます。
frame.appendChild(renderer.domElement)
これでframeが表示される時はTHREE.WebGLRendererオブジェクトが内容を描画する取り決めが成立したことになる。
varについては後述と書いたけど、長くなったので以下次回!












