シアトルコンサルティング サービス開発ブログ

シアトルコンサルティング株式会社プロダクトソリューション事業部の開発ブログです

three.jsでWebGL入門

ご無沙汰しています iijmyaです
3ヶ月ぶりの更新です。すみません・・

先日、私はWebGLJavaScriptライブラリである、「three.js」を使う機会がありました。
そこで、今回はthree.jsについてご紹介します!


1.WebGLとは

そもそもWebGLとは何なのでしょうか。

WebGLとは、ウェブブラウザ上で3次元空間を作り、仮想的な立体物を表示させるための標準仕様です。
WebGLは、2013年8月21日現在、Internet Explorerではバージョン10以下がサポートされていないため、Google Chromeでの閲覧が望ましいです


2.three.jsで3Dオブジェクトを描く(下準備)

それでは早速、three.jsを使ってWebGLを体験してみましょう!

three.jsのダウンロード

three.jsはこちらからダウンロードすることができます。

three.jsのjsファイルを読み込む

ダウンロードしたzipファイルを解凍すると、buildディレクトリの中に以下のファイルがあります。

  • three.js
  • three.min.js

今回は「three.min.js」をHTMLファイル内で読み込み、three.jsを使いましょう。

<script src="three.min.js"></script>

2.three.jsで3Dオブジェクトを描く

オブジェクトの描画工程

three.jsは内部的にcanvas要素を生成し、そこにオブジェクト(仮想的な立体物)を描画します。

オブジェクトを描画するには、以下の様な工程を踏みます。(場合によって順序が前後したり、省略する工程もあります)

  • シーンの作成
  • 表示するオブジェクトの作成
  • カメラの作成
  • 光源の作成
  • レンダラの作成
  • レンダリング
変数の定義

あらかじめ使用する値を変数に格納しておきましょう。

var width  = 600;            //横幅
var height = 600;            //縦幅
var fov    = 80;             //画角
var aspect = width / height; //画面アスペクト比
var near   = 1;              //クリッピング手前
var far    = 1000;           //クリッピング奥
シーンの作成

描画対象となる物体やその他のオブジェクトを格納するSceneクラスのインスタンスを作成します。
以降で作成するオブジェクトはすべてこのインスタンスに追加していき、最後にそれをレンダラに渡して描画します。

var scene = new THREE.Scene();
表示するオブジェクトの作成

実際に表示したいオブジェクトをシーンに追加します。
three.jsでは、表示するオブジェクトは以下の3つの要素で構成されます。

  • 形状 (Geometry)
  • 質感 (Material)
  • 実際に表示するオブジェクト (Mesh)
var geometry = new THREE.CubeGeometry(300, 300, 300); //幅、高さ、奥行きの指定
var material = new THREE.MeshLambertMaterial( { color: 0x77dd00 } ); //オブジェクトの色の指定
var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
カメラの作成

シーン内のどこから見た風景を描画するかを指定するカメラを作成し、シーンに追加します。

var camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
camera.position.z = 500;
光源の作成

オブジェクトを照らす光源をシーンに追加します。
光源を追加することで、オブジェクトの角度により明暗が出るため、より立体的に見えます!

var light = new THREE.DirectionalLight( 0xffffff, 3 ); //光の色と強さの指定
light.position.z = 3;
scene.add( light );
レンダラの作成

オブジェクトの描画処理を担うレンダラを初期化します。
描画領域のサイズなどを設定したあと、描画領域となるDOM要素を取得し、ドキュメントの任意の位置に挿入します。

var renderer = new THREE.WebGLRenderer({ antialias:true }); //アンチエイリアス処理有効
renderer.setSize( width, height ); //描画領域のサイズ設定
document.body.appendChild( renderer.domElement );
renderer.render( scene, camera );
レンダリング

以上の工程で表示させるシーンの準備が整ったのでレンダリングします。
静止画をただ描画するだけでは3D感が薄いので、今回はオブジェクトを回転させてみましょう。
オブジェクトの角度を変更するにはrotationプロパティを使用します。

function rendering(){
 mesh.rotation.x += 0.01;
 mesh.rotation.y += 0.01;
 renderer.render( scene, camera );
 setTimeout(rendering, 15);
}

rendering();
まとめ
<html>
<head>
  <meta charset="utf-8" />
  <title>three.jsでWebGL入門</title>
</head>
<body>
  <script src="./js/three.min.js" type="text/javascript"></script>
  <script>
  	var width  = 600;            //横幅
	var height = 600;            //縦幅
	var fov    = 80;             //画角
	var aspect = width / height; //画面アスペクト比
	var near   = 1;              //クリッピング手前
	var far    = 1000;           //クリッピング奥

	//------------------------------
	// シーンの作成
	//------------------------------
	var scene = new THREE.Scene();
	
	//------------------------------
	// 表示するオブジェクトの作成
	//------------------------------
	var geometry = new THREE.CubeGeometry(300, 300, 300); //幅、高さ、奥行きの指定
	var material = new THREE.MeshLambertMaterial( { color: 0x77dd00 } ); //オブジェクトの色の指定
	var mesh = new THREE.Mesh(geometry, material);

	scene.add(mesh);

	//------------------------------
	// カメラの作成
	//------------------------------
	var camera = new THREE.PerspectiveCamera( fov, aspect, near, far );

	camera.position.z = 500;

	//------------------------------
	// 光源の作成
	//------------------------------
	var light = new THREE.DirectionalLight( 0xffffff, 3 ); //光の色と強さの指定
	light.position.z = 3;
	scene.add( light );

	//------------------------------
	// レンダラの作成
	//------------------------------
	var renderer = new THREE.WebGLRenderer({ antialias:true }); //アンチエイリアス処理有効
	renderer.setSize( width, height ); //描画領域のサイズ設定
	document.body.appendChild( renderer.domElement );
	renderer.render( scene, camera );

	//------------------------------
	// レンダリング
	//------------------------------
	function rendering(){
		mesh.rotation.x += 0.01;
		mesh.rotation.y += 0.01;
		renderer.render( scene, camera );
		setTimeout(rendering, 15);
	}

	rendering();
  </script>
</body>
</html>

さて、ここまで書いたらHTMLファイルをブラウザ上で表示してみましょう。
くるくる回る立方体が表示されるはずです!
f:id:seattleservice:20130821155407p:plain



いかがでしたでしょうか。
WebGLJavaScriptライブラリ「three.js」でグラフィックの表現の幅が広がりますね。

タスクボードの活用

こんにちは iijmyaです。

私たちWebサービス事業部は、毎週金曜日にその週のフィードバックミーティング(以下、FBMTG)を行っています。

以前、FBMTGを通して挙がった問題の中に「タスクが見えにくい」というものがありました。
この問題の解決策として導入したのが、タスクボードです!


f:id:seattleservice:20130521181221j:plain:w600
手作り感が溢れていますね。


タスクの状況によって各エリアに振り分けを行います。

  • ToDoエリア…直近でやるタスクを振り分ける
  • Doingエリア…現在実行中のタスクを振り分ける
  • Doneエリア…完了したタスクを振り分ける

ちなみにタスクボードの下にはバックログエリアがあり、直近のToDoタスク以外をここに置いています。


それぞれのタスクシートはこのように記入しています。
f:id:seattleservice:20130521181244j:plain:w600
タスクを実行した日付と実行者のアイコン、見積もり時間と実績時間を記入しています。
あえて実行者名ではなくアイコンであるのは、決して名前を書くのが面倒だという訳ではなく、遊び心です。


このタスクボードを導入することでタスクが見える化し、お互いのタスク状況を把握しやすくなり、
また、見積もりと実績の差も見てすぐわかるようになりました。


最悪、紙とペンさえあれば、今からでも出来るタスクボード。皆さんも試してみてはいかがでしょうか。

パララックス効果を実現したページをscrolldeckで実現

こんにちは iijmyaです。

今回はscrolldeckを利用して、パララックス効果を実現してみましょう。


1.パララックス効果とは

パララックス(parallax)とは、直訳すると「視差」という意味です。
Web上で言われるパララックス効果とは、ページをスクロールする際に、画像や文字などが異なるスピードやタイミングで動作することを指します。


2.パララックス効果を実現する

言葉だけではなかなか想像し辛いと思いますので、実際にパララックス効果を実現したページを作ってみましょう。

scrolldeckのダウンロード

scrolldeck*1こちらからダウンロードすることができます。


scrolldeckのjsファイルを読み込む

scrolldeckを用いるには、以下のファイルを読み込みます。

<script type="text/javascript" 
 src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js" 
 charset="utf-8"></script>
<script src="js/jquery.scrollTo-1.4.2-min.js"></script>
<script src="js/jquery.easing.1.3.js"></script>
<script src="js/jquery.scrollorama.js"></script>
<script src="js/jquery.scrolldeck.js"></script>

ナビゲーションの初期化
$(document).ready(function() {
 var deck = new $.scrolldeck({
  slides: '.slide'
 });
});

この他にも「buttons」や「duration」などのオプションを指定することが出来ます。


対象モジュールにマークアップ

あとは、複数モジュールの親モジュールのclass属性の値に「slide」を指定して構成を作り、各モジュールに対して、「class=”animate-in”」や「data-animation」属性などの属性や属性値を付けてあげるだけです。

<div class="slide" id="para">
 <p  class="title animate-in" data-animation="fade-in">Parallax.</p>
 <p class="main animate-in" data-animation="fly-in-left">〜略〜</p>
 <div class="img animate-in" data-animation="fly-in-right">
  <img src="./img/sample.jpg" />
 </div>
</div>

data-animation属性の値によってパララックス効果が異なります。
 <例>

  • "fly-in-left"…対象モジュールが左側から現れる
  • "space-in"…対象モジュールが拡大された状態から現れる
  • "fade-in"…対象モジュールがフェードインする


イメージ画

f:id:seattleservice:20130517184526p:plain

スクロールしていくと・・・

f:id:seattleservice:20130517184535p:plain



以上です。
使い込めばかっこいいページを作ることが出来そうですね。

*1:scrolldeck…jQueryのプラグインのひとつ

gruntからrsyncする(syncDestIgnoreExclの話)

satkakuです。

gruntからrsyncしたいなーと思ってたら、案の定既にあったので、grunt-rsyncを試してみました。


  • 使い方

とりあえずインストールします。

% npm install grunt-rsync

Gruntfile.jsを以下のように書きます。

module.exports = function(grunt){
  grunt.initConfig({
    rsync: {
      dist: {
        src: "./",
        dest: "~/hoge",
        host: "remote",
        recursive: true,
        syncDest: true,
        exclude:[ "test/*" ]
      }
    }
  });

  grunt.loadNpmTasks('grunt-rsync');
  grunt.registerTask('deploy', ['rsync']);
};

excludeには、同期に含めたくないファイルのパターンを記述します。
これで、後は以下のコマンドを実行すれば終了です。

% grunt deploy

簡単!




とはいえ、いきなりリモートにぶん投げるのは怖いので、dry-runで一覧だけ見たいところです。

module.exports = function(grunt){
  grunt.initConfig({
    rsync: {
      dist: {
        src: "./",
        dest: "~/hoge",
        host: "remote",
        recursive: true,
        syncDest: true,
        dryRun: true,
        exclude:[ "test/*" ]
      }
    }
  });

  grunt.loadNpmTasks('grunt-rsync');
  grunt.registerTask('deploy', ['rsync']);
};


dryRunを指定してあげれば、リモートとの差分を一覧で出してくれます。簡単!


……ですが、実際に吐き出されたrsyncのコマンドは以下となっています。

rsync ./ remote:~/hoge --rsh=ssh --recursive --delete --delete-excluded --dry-run --verbose --exclude=test/*

delete-excludedがついちゃっています。delete-excludedが指定されていると、excludeで指定しているものについても、リモート上にあれば削除してしまいます。
例えば、ログファイルなど、リモートに同期したくないファイルをexcludeで指定していても、delete-excludedがついていることによりリモート上のファイルが消えてしまう結果になってしまいます。これは困る。

どうしようと思ってREADMEを見てみると、細かいオプションはrsyncwrapper使ってるから、そっちのドキュメント見てね、と書いてあります。

ということでrsyncwrapperを見てみると、syncDestIgnoreExclというオプションを使えばそんな感じのことが出来そうです。

これだ! と早速試してみますが、うまく行きません。何故? と思って、grunt-rsyncの中にあるnode_modulesを見てみると、中にあるrsyncwrapperのバージョンが0.0.12となっています。GitHubのコミットログを見ると、syncDestIgnoreExclが追加されたのはその後……!



##################################



ということで、grunt-rsyncのところで、npm installをして、rsyncwrapperを最新の0.0.13にします。
これで行けるはず!

module.exports = function(grunt){
  grunt.initConfig({
    rsync: {
      dist: {
        src: "./",
        dest: "~/hoge",
        host: "remote",
        recursive: true,
        syncDestIgnoreExcl: true,
        dryRun: true,
        exclude:[ "test/*" ]
      }
    }
  });

  grunt.loadNpmTasks('grunt-rsync');
  grunt.registerTask('deploy', ['rsync']);
};
rsync ./ remote:~/hoge --rsh=ssh --recursive --delete --dry-run --verbose --exclude=test/*

消えた! これで、ログファイルなどに関しても同期に含めないようにしつつ、リモートのファイルも削除しないように出来ました。

めでたし。

サイト上で動作するチュートリアルはIntro.jsで簡単作成!(入門編)

こんにちは iijmyaです。

今回は、自分が作成したサイトなどを説明するときに、堅苦しい説明書きを作らなくても視覚的にわかりやすく説明することができる救世主、「Intro.js」をご紹介します。


Intro.jsのダウンロード

Intro.jsは公式サイトからダウンロードすることができます。


Intro.jsの利用
それでは早速Intro.jsを使ってみましょう。

Intro.jsはダウンロードしてきた「intro.js」と「introjs.css」を読み込むことで使用することが出来ます。
HTML内にJavaScriptのコードを記述すると文字化けしてしまうことがあるため、charsetで文字コードも指定しておきます。

<script type="text/javascript" 
 src="//cdnjs.cloudflare.com/ajax/libs/intro.js/0.2.1/intro.min.js" 
 charset="utf-8">
</script>


次に、チュートリアルの対象にしたいモジュールに対し、data-intro属性*1とdata-step属性*2 を指定します。

<h2 data-step="1" data-intro="ここがタイトル部分です">intro.jsの利用</h2>


あとはIntro.jsを起動するモジュールを置き、イベント発生時の処理でIntro.jsを起動してあげれば終了です。

<button id="sampleIntrojsBtn">実 行</button>
 〜中略〜
jQuery(function($){
  $('#sampleIntrojsBtn').on('click', function(){
    introJs().start();
  });
});


Intro.jsの実行イメージ
今回の場合、実行ボタンをクリックすることでチュートリアルが表示されます。
f:id:seattleservice:20130514224805p:plain


Nextをクリックすることで次の説明に、Backをクリックすることで前の説明に戻ることが出来ます。
f:id:seattleservice:20130514224806p:plain

f:id:seattleservice:20130514224807p:plain


いかがでしたか?
またそのうちIntro.jsの応用編について書きたいと思います。

*1:data-intro属性…チュートリアルで表示したい説明文を指定する

*2:data-step属性…対象モジュールをチュートリアルの何番目に表示するかを指定する

コマンドラインからShift_JIS > UTF-8に変換する

satkakuです。

歴史を経て様々な人々によっていじられたプロジェクトでは、基本的な文字コードUTF-8なのに、特に意味も無く一部だけShift_JISになっていることなどがあります。ありました。

自分は主にMacで開発しており、エディタは大体Sublime Text 2を使っているのですが、Sublime Text 2はデフォルトではShift_JISに対応していないため、悲劇が生まれてしまいます。

ちなみに、Sublime Text 2でもShift_JISに対応させるプラグインはあります。
参考

ありますが、特に意味も無いのであれば、せっかくなのでUTF-8に揃えておきたいところです。

そこで今日はコマンドラインから、Shift_JISで書かれたテキストファイルをUTF-8に変換する方法を試します。

とりあえずShift_JISでテキストファイルを作っておきます。

f:id:seattleservice:20130511145550p:plain

残念!

それでは変換します。文字コード変換コマンドnkfを使いたいのですが、Macにはデフォルトでは入っていないので、homebrewでインストールします。

% brew install nkf
% nkf --help
Usage:  nkf -[flags] [--] [in file] .. [out file for -O flag]
 j/s/e/w  Specify output encoding ISO-2022-JP, Shift_JIS, EUC-JP
          UTF options is -w[8[0],{16,32}[{B,L}[0]]]
 J/S/E/W  Specify input encoding ISO-2022-JP, Shift_JIS, EUC-JP
          UTF option is -W[8,[16,32][B,L]]
 m[BQSN0] MIME decode [B:base64,Q:quoted,S:strict,N:nonstrict,0:no decode]
 M[BQ]    MIME encode [B:base64 Q:quoted]
 f/F      Folding: -f60 or -f or -f60-10 (fold margin 10) F preserve nl
 Z[0-4]   Default/0: Convert JISX0208 Alphabet to ASCII
          1: Kankaku to one space  2: to two spaces  3: HTML Entity
          4: JISX0208 Katakana to JISX0201 Katakana
 X,x      Convert Halfwidth Katakana to Fullwidth or preserve it
 O        Output to File (DEFAULT 'nkf.out')
 L[uwm]   Line mode u:LF w:CRLF m:CR (DEFAULT noconversion)
 --ic=        Specify the input encoding
 --oc=        Specify the output encoding
 --hiragana --katakana  Hiragana/Katakana Conversion
 --katakana-hiragana    Converts each other
 --{cap, url}-input     Convert hex after ':' or '%'
 --numchar-input        Convert Unicode Character Reference
 --fb-{skip, html, xml, perl, java, subchar}
                        Specify unassigned character's replacement
 --in-place[=SUF]       Overwrite original files
 --overwrite[=SUF]      Preserve timestamp of original files
 -g --guess             Guess the input code
 -v --version           Print the version
 --help/-V              Print this help / configuration
Network Kanji Filter Version 2.1.2 (2011-09-08) 
Copyright (C) 1987, FUJITSU LTD. (I.Ichikawa).
Copyright (C) 1996-2011, The nkf Project.

今回初めて知りましたが、nkfはNetwork Kanji Filterの略だったんですね。
かっこいい!

それはさておき、早速-gオプションをつけて、先ほどのファイルを見てみます。

% nkf -g sjis.txt
Shift_JIS

Shift_JISです。ですよね。分かってます。

さくっと変換しちゃいます。

% nkf -w sjis.txt > utf8.txt   

f:id:seattleservice:20130511150335p:plain

めでたしめでたし。

traceGLでクライアントサイドのJavaScriptの動きを見てみる

satkakuです。

昨日に引き続きtraceGLを色々試してみます。

昨日はサーバーサイドJavaScriptの出力を試したので、今日はクライアントサイドJavaScriptの出力を試してみようと思います。こっちのほうが使う機会は多いと思います。

まずは、昨日作ったサンプルページで、JavaScriptを読み込むよう追記しておきます。

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script src="javascripts/main.js"></script>

一つは、GoogleホスティングされているjQueryを読み込み、もう一つは/javascripts以下につくったmain.jsを読み込みます。

main.jsは以下の通りです。

(function(){
  $('button').on('click', function(e){
    call(function(){
      val = $('.source input').val();
      $('.dest').text(val);
    });
  });
})();

function call(func) {
  func();
}

ややこしい書き方をしていますが、要は、inputに書かれた文字をdestに表示するだけのコードです。

これを試してみます。

クライアントサイドJavaScriptをtraceGLで出力するようにするためには、プロキシを通してアクセスする必要がありますが、その辺はtraceGLがよしなにやってくれます。
では、やってみましょう。http://localhost:3000はあらかじめアクセス出来るようにしておきます。

% node tracegl http://localhost:3000

前回同様、traceGLの画面はhttp://localhost:2000で立ち上がっています。ここでhttp://localhost:3000にアクセスしても、traceGLの画面には変化がありませんので、プロキシが立っているhttp://localhost:2080にアクセスします。

f:id:seattleservice:20130509092004p:plain
f:id:seattleservice:20130509092218p:plain

traceGL画面に表示されました。
ここで、http://localhost:2080の画面上で「show」をクリックしてみます。

f:id:seattleservice:20130509092349p:plain
f:id:seattleservice:20130509092412p:plain

traceGL画面にon、callが実行されていく様子がリアルタイムで表示されました。右上の画面で行を選択すると、右下にそのコードが表示されます。左下はスタックトレースですね。

いい感じで実行状況をトレースできているようです。

ここで、試しにコンソールから直接JavaScriptをたたいてみましょう。

f:id:seattleservice:20130509092907p:plain
f:id:seattleservice:20130509093008p:plain

callが呼ばれたことが追加されました。実際にcallの引数に何が渡ったか見たかったのですが、それは表示されないようです。

では、Google上にホスティングされているjQueryの実行はどうなるでしょうか?

f:id:seattleservice:20130509093322p:plain

すると今度はtraceGLには何も変化がありません。ローカルにあるJavaScriptのみトレースしてくれるようです。

気になって、http://localhost:2080でmain.jsを見てみると……

f:id:seattleservice:20130509093635p:plain

書き換えられてる!

ちなみに、traceGL画面で、右下の領域の気になるところをダブルクリックすると、編集していたSublime Textの該当箇所にジャンプしました。どこまで賢くジャンプしてくれるかは、このコード量だとよく分かりませんが、これは便利そうです。

引き続き色々触ってみようと思います。