2015年5月12日火曜日

Cardboard実験サイト 6 / gyro.jsに含まれる関数、変数


デモサイト

ダウンロード

rotationRate(移動量)
rx = event.rotationRate.beta
ry = event.rotationRate.gamma
rz = event.rotationRate.alpha

acceleration(移動速度)
ax = event.acceleration.x
ay = event.acceleration.y
az = event.acceleration.z

orientation(初期状態に対する向き)
ox = event.alpha
oy = event.gamma

oz = event.beta

orientation(デバイスの向き)
"PU” portrait upside up
"PD” portrait upside down
"LL" landscape left
"LR" landscape right

例:
//Gyroオブジェクト生成
var gyro = new Gyro();
//x方向の相対位置
var ox  = gyro.ox;
//x方向の移動速度
var ax  = gyro.ax;

//x方向の移動量
var rx  = gyro.rx;

gyro.jsソース


devicemotion、devicemotionイベントハンドラを設定し、イベントからGyroscopeの情報を取得して変数にセットする。
accelerationの値からデバイスの縦、横位置を推測して変数にセットする。

Gyro = function() {
    try {
        if (event == null
            || typeof window.DeviceMotionEvent == "undefined"
            || typeof window.DeviceOrientationEvent == "undefined") {
            throw("Gyro not available.");
        }
        this.rx = this.ry = this.rz = this.ax = this.ay = this.az = 0;
        this.orientation = "";
        var gyro = this;
        window.ondevicemotion = function(event) {
            gyro.rx = event.rotationRate.beta;
            gyro.ry = event.rotationRate.gamma;
            gyro.rz = event.rotationRate.alpha;
            gyro.ax = event.acceleration.x;
            gyro.ay = event.acceleration.y;
            gyro.az = event.acceleration.z;
            gyro.orientation = "PU";
            if (gyro.ax < -5) gyro.orientation = "LL";
            else if (gyro.ax > 5) gyro.orientation = "LR";
            else if (gyro.ay > 5) gyro.orientation = "PD";
        }
        window. ondevicemotion = function(event) {
            gyro.ox = event.alpha;
            gyro.oy = event.gamma;
            gyro.oz = event.beta;
        }
    } catch(e) { alert(e); }

Cardboard実験サイト 5 / cardboard.jsに含まれる関数、変数

デモサイト

ダウンロード

Config
画面レイアウト、イベントハンドラ設定を行う。
コーディングを容易にするため、よく使用するオブジェクトを変数にセットする。

関数

Config.setBoxSizes()
ContainerとouterBox、およびboxL、boxRのサイズを設定する。
3DでboxL、boxRがある場合に用いる。

Config.setContainerSize()
ContainerとouterBoxのサイズを設定する。
2DでboxL、boxRがない場合に用いる。

変数

Config.conatiner
Config.outerBox
Config.boxL
Config.boxR
Config.ifL
Config.ifR
divのidに対応する変数
document.getElementIdで取得したオブジェクト。HTMLに該当のidのdivがない場合はnull。

Config.isIOS
iOSまたはAndroidの場合にtrue。
もともとiOSに対応するために設けた変数だが、Androidでも動作するのでその場合もtureに設定するようにした。

Config.winW
Config.winH
画面サイズに関する変数
ただし、isIOS==falseの場合はiPhone6のサイズ(667x375)を設定。

Config.centerX
Config.centerY
boxL、boxRの中心の位置

Config.addClickEvent
イベント設定制御
デフォルト値はtrueで、outerBoxにtouchstartまたはclickイベントハンドラをセットする。
デフォルトではダブルタップ(またはクリック)時は左画面の場合は上の階層に戻り、右画面の場合はreloadを行う。
ただしiframeを使用する構成などでイベントが渡ってこない場合は実行されない。
イベントハンドラが不要な場合はsetBoxSizesまたはsetContainerSizeを呼ぶ前にこの変数の値をfalseにセットする。

Config.onclick
シングルタップ(またはクリック)時はデフォルトでは何も行わない。
この変数にfunctionをセットしておくと、それを実行する。

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

Canvas
描画エリアにオブジェクト追加。
タイマーイベントでアニメ描画。

関数

Canvas.add(func)
描画を行うオブジェクト(function)を追加する。
func : Partsのサブクラス。
左右の画面の各々にnew func(..)でオブジェクトを生成し、それをひとつにまとめLRPairオブジェクトを生成して返す。

Canvas.remove(obj)
Canvasに登路されたオブジェクトを削除する。
objはCanvas.addが返したLRPairオブジェクト。

Canvas.clear()
Canvasに登録されたオブジェクトを全て削除する。

Canvas.start()
アニメーションを開始する。

変数

Canvas.interval
アニメーション実行間隔(msec)。直前の描画開始から少なくともこのミリ秒が経過してから次の描画を開始する。
描画にかかった時間がこれ以上の場合はすぐに次の描画を開始する。
デフォルト値=50msec。

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


LRPair
 左右二つの描画エリアをまとめて扱う。
 Canvas.addで追加されたfuncのオブジェクトを左右各々生成し、保持する。

setParam(param)
 保持している左右のオブジェクトの各々にパラメータをセットする。
 param: key-valueペアの配列。{key : value, ... }
 パラメータの扱いはPartsオブジェクトに依存。

move() 
 保持している左右のオブジェクトの各々のmove関数を呼ぶ。

プロパティー

innerText
 保持している左右のオブジェクトの各々が配置されているdivのinnerTextの値の設定。
 取得の場合は左側のdivのinnerText(通常は左右同じ値)。

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

Parts
 Canvas.addの引数につかうクラス。実際の描画はサブクラスに実装する。

関数

setParam(param)
パラメータ設定。
param: Paramオブジェクト

applyParam()
setParamで設定されたパラメータをオブジェクトに反映する。
実際のロジックはサブクラスで実装する。

move()
タイマーイベントで呼ばれ、描画を実行する。
実際の描画はサブクラスに実装する。

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

Param
 key−value辞書

Param.val(key)
 オブジェクトが保持するkey−value辞書からkeyに対応するvalueを返す。

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

Objectへのプロパティー追加

param
 オブジェクトのdictの値の設定、取得。

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

その他

画面がスワイプで動かないようにするため、touchmoveイベントをキャンセルする。

<body ontouchmove="blockMove(event)">

function blockMove(event) {
if (Config.isIOS) event.preventDefault();
}


Cardboard実験サイト 4.1 Gyro / Panorama

概要

Gyroscopeのデータを取得して、デバイスの移動に応じて画面を動かすサンプルです。
360°のパノラマ写真をGyro連動で回転させます。

iOS/Androidで基本的に同じ使い方ができますが、Androidでのテストは行っていません。動作不良の場合は若干の修正で対応できるはずです。

画面レイアウト設定
タグ構造 
HTML/Photo1とほぼ同じですが、styleを変更するためにclassを設定しています。
msgDivは使い方、写真タイトルを表示するエリアです。
    <body onload="init();">
        <div id="container" class="picFrame">
            <div id="outerBox" class="pic">
                <div id="msgDiv"></div>
            </div>
        </div>
    </body>

index.htmlのjavascript
js/cssインポート
        <script src="../../js/cardboard.js"></script>
        <script src="../../js/gyro.js"></script>
        <link rel="stylesheet" type="text/css" href="../../css/cardboard.css" />
        <link rel="stylesheet" type="text/css" href="Panorama.css" />

javascript
        var gyro = null;            
        function init() {
             //デバイス横位置の大きさに合わせて左右の画面をリサイズ、イベント設定を行う。
             Config.setContainerSize();
             //イベントハンドラ設定
             Config.onclick = changeImage;
             //最初の画像を表示
             changeImage();
             //Gyroオブジェクト生成
             gyro = new Gyro();
             //タイマーイベントスタート
             setTimeout(move, 33);
        }

        var posX = 0;

        function move() {
            //絶えず値が変動するので、細かすぎる動きは無視する。
            //gyroからデバイスの位置を取得
         //gyro.ox:  device orientation alpha 
            if (Math.abs(posX - gyro.ox) > 0.1) {
                posX = gyro.ox + offsetX;
                var x = (imgWidth * posX / 360).toFixed(1);
                Config.outerBox.style.backgroundPosition = x + "px";
            }
            setTimeout(move, 33);
        }

        //ダブルタップで画面チェンジ。
function changeImage(event) { with(Config.outerBox.style) { backgroundImage = "url("+ imgUrl +")"; backgroundOrigin = "0px 0px"; } //画像サイズ取得のためにimgに画像をセット。 var img = document.createElement("img"); img.addEventListener("load", imgLoaded); } var imgWidth = 0; var offsetX = 0; //img.onloadイベントハンドラ。imgから画像サイズを取得、初期表示位置(offsetX)をセット。 function imgLoaded(event) {
                var srcElm = event.srcElement;
                imgWidth = Math.round(srcElm.width * (document.body.clientHeight / srcElm.height));
                offsetX = (event.srcElement.width - Config.outerBox.clientWidth) / 2;
                event.srcElement.removeEventListener("load");
        }

2015年5月11日月曜日

Cardboard実験サイト 3 / Threeサンプルの構成


デモサイト

ソースコードダウンロード

概要

WebGLをjavascriptライブラリThree.jsで作られたHTMLを二分割画面で再生することで3Dアニメーション化するサンプルです。

画面レイアウト設定

タグ構造 

Three.jsを使うjavascriptを自分で作る場合(Cube1、Sphere1)
HTMLサンプルと同じです。

  <body onload="init();">
    <div id="container">
      <div id="outerBox">
        <div id="boxR">
          <div id="canvasR"></div>
        </div>
        <div id="boxL">
          <div id="canvasL"></div>
        </div>
      </div>
    </div>
  </body>

Three.orgのexampleなど、既存のjavascriptを利用する場合
HTMLサンプルとほぼ同じですが、Canvasのdiv代わりにiframeを使い、Three.jsのHTMLを読み込みます。
javascript、cssはdivのidを使用するので、idはこのとおりにしておきます。

  <body onload="init();">
    <div id="container">
      <div id="outerBox">
        <div id="boxL">
          <iframe id="ifL" src="webgl_animation_cloth.html"></iframe>
        </div>
        <div id="boxR">
          <iframe id="ifR" src="webgl_animation_cloth.html"></iframe>
        </div>
      </div>
    </div>
  </body>

index.htmlのjavascript

Three.jsを使うjavascriptを自分で作る場合(Cube1、Sphere1)
ja、cssインポート

    <script src="../build/three.min.js"></script>
    <script src="../../js/cardboard.js"></script>
    <script src="Cube.js"></script>
    <link href="../../css/cardboard.css" rel="stylesheet" type="text/css"></link>

javascript

    //body.onloadで呼び出し、初期化を実行。
    function init() {
        Config.setBoxSizes();
        Canvas.add(Cube);
        Canvas.start(msec);
    }

Three.orgのexampleなど、既存のjavascriptを利用する場合
js, cssインポート

    <script src="../../js/cardboard.js"></script>
    <link href="../../css/cardboard.css" rel="stylesheet" type="text/css"></link>

javascript
//body.onloadで呼び出し、初期化を実行。 function init() {   //デバイス横位置の大きさに合わせて左右の画面をリサイズ、イベント設定を行う。 Config.setBoxSizes();   //視差を設定 Config.ifL.contentWindow.param = new Param({"cameraX":0}); Config.ifR.contentWindow.param = new Param({"cameraX":0.05}); }

既存のjavascriptの場合、リンクのパス、アニメ同期に関わる部分の変更が必要。
描画、アニメ同期は元のjavascriptで行うので、ここではCanvas.startは呼ばない。

Three.orgのexampleの変更箇所
exampleによって変更箇所が異なるが、以下のような箇所を変更する。

      //画面サイズ設定
      var boxH, boxW;
      function init() {
          boxH = parent.Config.winH;
          boxW = Math.floor(parent.Config.winW / 2);
          ....
          //Cameraの領域設定
          //camera = new THREE.PerspectiveCamera( 30, window.innerWidth / window.innerHeight, 1, 10000 );
          camera = new THREE.PerspectiveCamera( 30, boxW / boxH, 1, 10000 );
          ....
          //texture相対パス変更
          //var clothTexture = THREE.ImageUtils.loadTexture( 'textures/patterns/circuit_pattern.png' );
          var clothTexture = THREE.ImageUtils.loadTexture( '../examples/textures/patterns/circuit_pattern.png' );
          ....
          //models相対パス変更
           //loader.load( "models/animated/horse.js", function ( geometry ) {
    loader.load( "../examples/models/animated/horse.js", function ( geometry ) {
      }

      //canvas_particles_waves.htmlの場合のグローバル変数
      var count, mouseX;

      function render() {
          //Dateを使用している場合は左右の同期が取れるが、マウス位置やループ毎の加算のような場合は変更が必要。
         count = Date.now() / 500; //マウス位置をDateでせって
         mouseX = mouseY = 0;
          //cameraの位置に視差を設定
          if ( rotate ) {
              //初期亜k時に設定したパラメータでx方向位置を調整
              var x = (typeof param == "undefined" ? 0 : param.cameraX);
              //camera.position.x = Math.cos( timer ) * 1500;
              camera.position.x = Math.cos( timer ) * 1500 + x;
              ..... 
          }
      }

リンクのパス
<script src="../examples/js/Cloth.js"></script>など
このサンプルでは同じになるように配置してあるが、異なる場合は構成に応じて変更。

2015年5月8日金曜日

Cardboard実験サイト2.1 / HTML (div構成)

概要

iPhoneを横位置にしたときに画面を二分割し、視差のあるイメージを表示します。
共通のjavascript(cardboard.js)は画面レイアウト設定と、左右の画面に対する処理を一括して行う機能を提供します。
タイマーイベントで描画関数を呼び、オブジェクトを移動させ、アニメを作ります。

このサンプルではdivだけで画面を構成しています。同一window内にあるため変数を共有でき、アニメ描画のためのループも左右で同じタイミングで行えます。

残念ながら、translate、rotateの結果divからはみ出してもクリッピングしてくれません。
クリッッピングが必要な場合はCardboard実験サイト2.2 / HTML (iframe構成)をご覧ください。

画面レイアウト設定
タグ構造 

bodyタグ内は次のようにdivを数階層積み重ねたものです。
javascript、cssはdivのidを使用するので、idはこのとおりにしておきます。

  <body onload="init();" ontouchmove="blockMove(event)" >
    <div id="container">
      <div id="outerBox">
        <div id="boxR">
          <div id="canvasR"></div>
        </div>
        <div id="boxL">
          <div id="canvasL"></div>
        </div>
      </div>
    </div>
  </body>

index.htmlのjavascript
js/cssインポート

    <script src="../../js/cardboard.js"></script>
    <script src="../js/Plate.js"></script>
    <script src="Plate1.js"></script>
    <link rel="stylesheet" type="text/css" href="../../css/cardboard.css" />

javascript
index.html

    //body.onloadで呼び出し、初期化を実行。
    function init() {
        Config.setBoxSizes();
        Config.setParspective(parsXd, parsYd, parsZ);
        var obj = Canvas.add(Part);
        obj.setParam({key:val, ... });
        Canvas.start();
    }
      function blockMove(event) {
          event.preventDefault();
      }

Plate1の場合
index.html

    function init() {
          Config.setBoxSizes();
          Config.setParspective(4, 0, 100);

          var tx = Config.centerX - 50;
          var ty = Config.centerY - 35;

          var p1 = Canvas.add(Plate1);
          p1.setParam({"tx":tx, "ty":ty, "tz":50, "rx":0, "ry":0, "rz":0, "c":"#ddf" });

          var p2 = Canvas.add(Plate1);
          p2.setParam({"tx":(tx-10), "ty":(ty-10), "tz":40, "rx":50, "ry":50, "rz":50, "c":"#dfd" });

          var p3 = Canvas.add(Plate1);
          p3.setParam({"tx":(tx+10), "ty":(ty+10), "tz":30, "rx":-50, "ry":-50, "rz":-50, "c":"#fdd" });

          Canvas.start();
      }

Plate1.js

    Plate1 = function(parentDiv, side, div) {
          //Plateのコンストラクタを継承。PlateはPartを継承。
          Plate.apply(this,arguments);
          this.div.innerText = "\n 3D Sample \n ";
          this.div.style.border = "solid 1px black";
    }
     //Plataのprototypeを継承
    Plate1.prototype = new Plate();
    //パラメータを変数にセット。
    Plate1.prototype.setParam = function(param) {
        this.Param = param;
        this.tx = param["tx"];
        this.ty = param["ty"];
        this.tz0 = this.tz = param["tz"];
        this.rx = param["rx"];
        this.ry = param["ry"];
        this.rz = param["rz"];
        this.div.style.backgroundColor = param["c"];
    }
    //Canvasのタイマイベントで呼ばれる。
    Plate1.prototype.move = function() {
        this.rx += 1;
        this.ry += 0.5;
        this.rz += 1;
        if (this.tz > -150)
            this.tz -= 2;
        else
             this.tz = this.Param["tz"];;
        this.div.style.webkitTransform = "translateX(" + this.tx + "px) "
                                                              + "translateY(" + this.ty + "px) "
                                                              + "translateZ(" + this.tz + "px) "
                                                              + "rotateX("+ this.rx + "deg) "
                                                              + "rotateY("+ this.ry + "deg) "
                                                              + "rotateZ("+ this.rz + "deg) ";
    }

canva.jsの関数

Config.setBoxSizes();
Config.setFrames();
Config.setFrameCanvas(window.name);
  デバイス横位置の大きさに合わせて左右の画面をリサイズ、イベント設定を行う。

Config.setParspective(parsXd, parsYd, parsZ);
  視点、視差を設定。
  parsXd 画面中心からの左右距離(px)。
                左画面はマイナス、右画面はプラスし、視差を作る。
  parsYd 画面中心からの上下距離(px)      
  parsZ   画面からの遠近距離。

var obj = Canvas.add(Part);
    Canvasにオブジェクトを追加。
  Part Parts(後述)のサブクラス。
  
  obj.setParam(param);
    param objが使用するパラメータを設定。
                例: {"tx":tx, "ty":ty, "tz":50, "rx":0, "ry":0, "rz":0, "c":"#ddf" }
                     パラメータのキー定義、値の適用はPartが実装。

 Canvas.start();
  タイマーイベントスタート。
  デフォルトは50msecの間隔でイベント実行。
  描画に50msec以上かかる場合は、描画完了後に次のイベントを実行。

  Part.prototype.move();
    タイマーイベントで呼ばれるfunction。
    デフォルトでは何も行わないので、各Partsで実行する。