HTML5+Three.jsで3Dプログラミングに挑戦!

丸坊主なのに寝癖が付く男、正宗です。前回の記事「Actionscript3erが覚えるJavascriptでのクラス開発まとめ」でjavascriptをActionscript3ライクに書く方法をまとめてみたので、今度は練習がてらHTML5をさわってみました。

WebGL版です。

クリックで別ウインドウで開きます。
クリックで別ウインドウで開きます。

画像クリックすると別ウインドウで開きます。
うまく動かない場合はWebGLを使わない素のCanvasレンダリングも作ってみましたのでこちらのリンク先を参照してください。
スクロールで3D空間をうねうね動く的なことがやりたいんだろうな、って思ってもらえたらうれしいです。ちなみに背景には旅行の思い出の写真をあしらって、ナイスな感じに仕上げました。
ソースは適当にほじくって見てみてください。

今回は、はじめてHTML5を触ってみた中でわかったことを書きたいと思います。

HTML5でJavascriptからグラフィックを操作するには、従来のdivの操作に加えてSVGとCanvasを使う方法が加わったらしく、とりあえず今回はCanvasを使ってみました。

3Dライブラリthree.jsについて

ご存じのとおり、SVGはベクターを扱うタグでして、Canvasはピクセルを扱う場所になります。AS3だとベクターもラスターもどっちもよく扱うのでJSでも出来るんだろうけど流石に今回ピクセル操作ばっかりプログラミングするのは面倒くさかったので何かいいライブラリはないかと思っていると、どうやら3Dのライブラリthree.jsが何やら面白そうです。
ある程度のJavascriptの知識と、3Dライブラリを使ったプログラムの経験があればすんなりと使うことが出来ました。
がんばってAPIを掘り下げれば、かなり面白いものが作れそうです。

注意すべき点は、たぶんバージョンアップのためだと思うのですがAPIの仕様が変わっていて、古い解説文書などですと動かない場合があることです。
あとどうしてもドキュメントが少ないので、特にリファレンスが無いと何も出来ない僕にとっては、慣れ親しんだASDocくらい詳しいリファレンスが無いのが地味に大変でした。

ただし、クラス名やプロパティに変な癖も無いのでリファレンスが足りて無くても何とかなりました。
一般的な3Dライブラリと似たような感じで

  • シーンを作って、カメラを作って、レンダラーを作って
  • シーンや表示オブジェクトは入れ子構造にできて
  • ジオメトリとマテリアルを持つメッシュを作成して表示オブジェクトに追加
  • シーンとカメラを指定してレンダリングを実行

という、ごくごく自然な流れでプログラミングできました。

面白いことに、WebGLでレンダリングするレンダラーと、素のCanvasにレンダリングするレンダラーがあるんですが、その二つをかなり簡単に切り替えられるんです。
ここらへんは型付けがゆるいJavascriptならではの面白みだと思いました。

制作環境について

かなり残念な英語力と記憶力、たぐいまれなるタイピングミスの持ち主の僕にとって、開発環境こそが頼みの綱です。
今回は@kotaro_tanさんに教えて頂いたWebStormというIDEを使ってみました。

なにやらかっこいいクラスを作ってるなう
なにやらかっこいいクラスを作ってるなう

コードに色がたくさんついて綺麗なので気に入っています!

Javascriptをクラスで開発していくことについて

前回の記事「Actionscript3erが覚えるJavascriptでのクラス開発まとめ」でJavascriptでクラスを作って開発するスタイルをまとめてみたわけですが、手前味噌ながらこれが非常に役に立ちました。
javascriptにはjavascriptの面白さがあるので、AS3のクラスっぽい作り方が無理矢理なのであれば何もわざわざjavascriptの面白さを消してまでクラス作りをする必要は全くないと思っていたのですが、無理矢理どころかむしろだいぶ自然にクラスが使えたので、だいぶ効率よく作ることが出来ました。
後述するjsファイルの重複ロード問題も今回はクラスを使って解決できましたし、デザインパターンが使えるのもなによりうれしいひなまつりです(こんど娘が初節句なんです。楽しみで楽しみで)。
クラスは僕も最初かなり苦手意識を持っていましたが、品質を上げるための先人の知恵の結晶なので今後ももっともっと勉強していきたいです。

Javascriptのゆるさについて

Javascript特有の「ゆるさ」は長所でもあり短所でもあるんですが、久々にまあまあの量のJavascriptをコーディングして、このゆるさもかなり楽しめました。
個人的にはガチガチの型付け言語をガチガチのIDEで扱った方が実質的なコーディング速度は速いと思うんですが、Javascriptの設計のゆるさからくる「アイデアが形になるまでの速度感」はAS3とはまた違った面白さがあります。
AS1の頃の面白さとHTML5の新鮮さの良いところどりはずるいと思います。

javascriptの楽しさをたっぷり楽しんだ上で、今後の課題も書き留めておきたいと思います。
あくまでActionscript3よりな人間が久々に遊びでJavascript触ってみて対応というか妥協した程度の記録ですので、今後かならず解決するべきだしもっといいノウハウは他にあるはずです。

変数やオブジェクトがいくらでも上書きできてしまう

定数は無理としても、prototypeに閉じ込めるなどしてprivateな空間は作るべきなのでしょうが、今回はそこまでしませんでした。変数のアクセス範囲を出来るだけ狭くすることが鉄則なのに、非常に悩みどころです。

名前空間について

いちおう最初のファイルに

if(!jp_utweb_namespace){
    var jp_utweb_namespace = {};
}

こういう事書いておくことで「俺はグローバルの名前空間をあんまり汚染しない男だぞ」アピールをしているのですが、正直気に入っていません…。
最低でもプロジェクトごとにも別けたいし、ネームスペースの変数名そのものを持ち回りたいんですが、そこらへんは今後の課題として残りました。

重複ファイルのロードについて

こういったjavascriptファイルがあったとして、
onece.js

;(function(ns){
    alert('一回しか実行を想定していない処理!');
})(jp_utweb_namespace);

HTMLで二回読み込まれてしまうと


当然二回実行されてしまいます。
実行前にDOMを調べて、src属性に自分のファイル名と同じscriptタグが2つ以上ある場合は一回しか実行しない、といった処理をすればいいのですが、うまくライブラリ化できなかったので、それは今後の課題になります。

今回とった方法では、クラスを作成する処理ばかりにしておいて、最後にrun.jsというスクリプトファイルのみ、重複チェックを行って、ActionScriptでいうドキュメントクラスに相当するクラスを一回だけ実行する、というやり方にしました。

クラスを作成する直前に

;(function(ns){
    if(!!ns.Mein){
        return;
    }
    ns.Main = function(){};
})(jp_utweb_namespace);

こんな感じでチェックを入れても良かったのですが、タイプミスなどによるデバッグがしづらくてかえって危険なのでやめました。
実際に上のコードはこんなに短いのに見つけるのが困難なバグがあります。
ここは素直に

;(function(ns){
    ns.Main = function(){};
})(jp_utweb_namespace);

こう書くことにしました。
重複ロード時にクラスが複数回生成されてしまうコストが発生しますが、プログラムの意図しない箇所でバグるよりはマシかと。

まとめ

いまのところまだちょっと触って遊んでみた程度ですので、今後案件に投入できるかどうかの判断もまだ現段階ではつきませんが、面白い技術であることには間違いないです。
少なくともWEB上でリッチなインターフェースやモーション、体験を作るということにおいてはActionScripterこそ親和性の高い技術なので、これからどんどんと横断的に開発できるノウハウを見つけ出してハイブリッドな開発者がたくさん増えると面白いかと思います。

コメントを残す

メールアドレスが公開されることはありません。