2015年6月9日火曜日

Cardboard実験サイト2.3 / HTML (div構成 / Photo1 - ステレオ写真)

概要
あらかじめ作ったステレオ写真を表示します。
これはステレオ写真をハコスコで見られるようにしようと作ったもので、画面分割は行っていません。

画面レイアウト設定
index.htmlで画面レイアウトのためのタグ構造を作り、画面サイズに応じてcardboard.jsでレイアウト設定を行います

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

  <body onload="init();" ontouchmove="blockMove(event)" >
    <div id="container">
      <div id="outerBox" class="photo" onclick="changeImage()">
      </div>
    </div>
  </body>

javascript
index.html


      function init() {
          //divの配置
          Config.setContainerSize();
          //最初の画像表示
          changeImage();
      }

      //画像名配列
      var arr = new Array("image1.jpg", ""image2.png", ...);
      var ix = -1;

      //clickまたはtouchstartイベントで呼ばれ、画像を切り替える。
      function changeImage() {
          //右画面で次へ進み、左が画面で前に戻る。
          if (event.pageX == null) 
              ix = 0;
          else
              ix += (event.pageX > (Config.winW / 2) ? 1 : -1);
          if (ix >= arr.length)
              ix = 0;
          else if (ix < 0)
              ix = arr.length - 1;
          //divのbackgroundImageにセット。
          with(document.getElementById("outerBox").style) {
              backgroundImage = "url(Images/" + arr[ix] + ")";
              backgroundSize = "100%";
          }
      }

      //スワイプされても画面を動かさないようにする。
      function blockMove(event) {
        if (Config.isIOS) event.preventDefault();
      }

Config.setContainerSize();
  デバイス横位置の大きさに合わせて画面をリサイズ、イベント設定を行なう。
  また、デフォルトで次のclickまたはtouchstartイベントハンドラをセットする。
  左画面ダブルクリック 上の階層に戻る
  右画面ダブルクリック location.reload();
  シングルクリック   Config.onclickにfunctionが設定されていればそれを実行、
                                   さもなければなにもしない。

 イベントハンドラが不要な場合はsetContainerSizeを呼ぶ前に次の行を追加。
 Config.addClickEvent = false;

 Photo1ではdivにonclickイベントハンドラを設定することで上記設定を置き換えている。

Cardboard実験サイト 2.2 / HTML (iframe構成)

概要
iPhoneを横位置にしたときに画面を二分割し、視差のあるイメージを表示します。
iframeを使用しています。

二画面が各々独立したwindowとなり、translateの結果divからはみ出した部分はクリッピングされます。

一方、独立したwindowのためタイマーイベントのループも別々タイミングで行われるため、単純にループ内で定数を足すような方法では、時間経過とともに同期のズレが発生します。Dateの時刻を利用することで左右のズレを避けることができます。

javascriptはcardboard.jsとcardboard−iframe.jsをインポートします。cardboard−iframe.jsはcardboard.jsへのfunctionを追加と一部置き換えを行います。これらは
画面レイアウト設定と、左右の画面に対する処理を一括して行う機能を提供し、また
タイマーイベントで描画関数を呼び出します。

画面レイアウト設定
index.htmlで画面レイアウトのためのタグ構造を作り、画面サイズに応じてcardboard−iframe.jsでレイアウト設定を行います

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

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

Part.html (iframeのsrc)
    <body onload="init();">
        <div id="container">
            <div id="outerBox">
                <div id="canvas"></div>
            </div>
        </div>
    </body>


js/cssインポート
        <link rel="stylesheet" type="text/css" href="../../css/cardboard.css" />
        <script src="../../js/cardboard.js"></script>
        <script src="../../js/cardboard-iframe.js"></script>
        <script src="../../js/gyro.js"></script>

cardboard.jsの後にcardboard-iframe.jsを追加。

javascript
index.html
    //body.onloadで呼び出し、初期化を実行。
    var gyro = null;
    var startTime = new Date().getTime();
    function init() {
        //cardboad.jsのGyroオブジェクト生成。
         gyro = new Gyro();
         //div, iframeの配置。
         Config.setFrames();
    }

Part.html (ifarmeのsrc)

             //onloadイベント
             function init() {
             //iframe内のdiv配置。
             Config.setFrameCanvas(window.name);
             //iframeのサイズがjavascriptで決定できず表示位置がズレるので位置を調整。
             Config.body.scrollLeft = 0;
             //視点設定(イタリックは実際の値で置き換え)
             Config.setParspective(Config.side=="L"?-4:4, parsY, parsZ);
             //描画オブジェクト追加。
             var obj = Canvas.add(Part);
             //パラメータ設定。paramはkey/valueのArray。JSONなら{key1:value1, key2:value2, ...}。 
             obj.setParam(param);
             //タイマーイベントスタート。
             Canvas.start();
        }

Cube2.js
    //cardboard-iframe.jsのCanvas.add(func)実行中に呼ばれる。
    Cube2 = function(parentDiv, side) {
        //HTMLに配置したCubeのdivをコピーする。
        this.div = document.getElementById("divFaces").cloneNode(true);
        this.div.className = "o3d";
        this.div.style.display = "block";
        //parentDivに追加。
        parentDiv.appendChild(this.div);
    }

    //cube.htmlのaddCube(param)から呼ばれる。
    Cube2.prototype.setParam = function(param) {
        this.ty = -70;
        this.rx = this.ry = this.rz = this.tx = this.ty = this.tz = 0;
        this.dx = param["dx"] == null ? 0 : param["dx"];
        this.dy = param["dy"] == null ? 0 : param["dy"];
        this.r = param["r"] == null ? 0 : param["r"];
    }

    //Canvasのタイマーイベントで呼ばれる。
    Cube2.prototype.move = function() {
        //index.htmlのonloadが実行されるまではgyroがnull。
        if (parent.gyro == null) return;
        //Dateの時刻を利用してアニメ用の変数を設定。
        var f = new Date().getTime() / 50;
        this.rx = f * 0.8;
        this.ry = f * 0.9;
        this.rz = f;
        //gyroから値を取得。
        var gx = (parent.gyro.ox + this.dx) * Math.PI / 180;
        var gy = (Math.abs(parent.gyro.oy) + 90) * Math.PI / 180;
        //オブジェクトの座標変換。
        var tx = this.r * Math.sin(gx) + Config.centerX;;
        var tz = this.r * Math.cos(gx) * Math.cos(gy);
        var ty = tz * Math.sin(gy);
        var tt = ty;
        ty -= this.r * Math.sin(this.dy * Math.PI / 180)
        this.div.style.webkitTransform = "translateX(" + tx + "px) "
            + "translateY(" + ty + "px) "
            + "translateZ(" + tz + "px) "
            + "rotateX("+ this.rx + "deg) "
            + "rotateY("+ this.ry + "deg) ";
    }

2015年6月7日日曜日

Cardboard実験サイト 4.3 Gyro / Cube2 (iframe構成)

概要
Gyroscopeのデータを取得して、デバイスの移動に応じて画面を動かすサンプルです。

このサンプルでは左右の画面をiframeで構成し、視差を付けて3D画像を描画します。

iframeを使用することで、左右の画面各々でクリッピングが行われるようになります。
一方、各々が独立したwindowのためタイマイベントも別々にループし、アニメ描画時に単純にループ毎に定数を足すような演算では時間が経つにつれ描画にズレが生じます。
それを避けるため、ここでは親window(index.html)から時間経過(msec())を取得し、それに基づいてアニメ描画を行っています。

HTML/Cube1のdivを組み合わせて作る立方体を複数配置し、Gyroと連動して視点を移動させます。感覚的には頭の動きに合わせて自分の周りを眺めるような感じです。座標の中心から視点を離す必要があるため、空間の中心からは少しズレがでます。

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


画面レイアウト設定

タグ構造 
<body onload="init();" ontouchmove="blockMove(event)">
    <!-- HTMLL/Cube1と同じ -->
    <div id="container">
      <div id="outerBox">
        <div id="boxR" onclick="restart()">
          <div id="canvasR"></div>
        </div>
        <div id="boxL" onclick="back()">
          <div id="canvasL"></div>
        </div>
      </div>
    </div>
    <!-- Cubeを組み立てる6面のdiv -->
    <div id="divFaces" style="display:none">
        <div id="cube">
            <div class="face" id="f1">One</div>
            <div class="face" id="f2">Two</div>
            <div class="face" id="f3">Three</div>
            <div class="face" id="f4">Four</div>
            <div class="face" id="f5">Five</div>
            <div class="face" id="f6">Six</div>
        </div>
    </div>
</body>

is/cssインポート
        <script src="../../js/cardboard.js"></script>
        <script src="../../js/gyro.js"></script>
        <script src="../../HTML/js/Cube.js"></script>
        <script src="Cube1.js"></script>
        <link rel="stylesheet" type="text/css" href="../../css/cardboard.css" />
        <link rel="stylesheet" type="text/css" href="Cube1.css" />

javascript
index.html
        var gyro = null;
        function init() {
              //Gyroオブジェクト生成
              gyro = new Gyro();
              //デバイス横位置の大きさに合わせて左右の画面をリサイズ、イベント設定を行う。
              Config.setBoxSizes();
              //視点の設定
              Config.setParspective(4, 0, 500);
             //Cubeオブジェクト追加
              var c1 = Canvas.add(Cube1);
              //タイマーイベントスタート
              Canvas.start(50);
        }
        //スワイプで画面が動かないようにする。
        function blockMove(event) {
              if (Config.isIOS) event.preventDefault();
        }

Cube1.js
    //コンストラクタ
    Cube1 = function(parentDiv, side) {
        if (parentDiv == null) return;
        this.div = document.getElementById("divFaces").cloneNode(true);
        if (this.div == null) throw 'Missing <div id="divFaces">';
        this.div.className = "o3d";
        this.div.style.display = "block";
        parentDiv.appendChild(this.div);
    }

   //パラメータ設定
    Cube1.prototype.setParam = function(param) {
        this.ty = -70;
        this.rx = this.ry = this.rz = this.tx = this.ty = this.tz = 0;
        this.dx = param["dx"] == null ? 0 : param["dx"];
        this.dy = param["dy"] == null ? 0 : param["dy"];
        this.r = param["r"] == null ? 0 : param["r"];
        this.rand = param["rand"] == null ? 0 : param["rand"];
    }

    //Canvasのタイマーイベントから呼ばれる。アニメ描画。
    Cube1.prototype.move = function() {
        if (parent.gyro == null) return;
        var f = parent.msec() / 10000;
        this.rx += f * 0.8;   //+ this.rand;
        this.ry += f * 0.9; // + this.rand;
        this.rz += f;   // + this.rand;
        
        var gx = (parent.gyro.ox + this.dx) * Math.PI / 180;
        var gy = (Math.abs(parent.gyro.oy) + 90) * Math.PI / 180;
        
        var tx = this.r * Math.sin(gx) + Config.centerX;;
        var tz = this.r * Math.cos(gx) * Math.cos(gy);
        var ty = tz * Math.sin(gy);
        var tt = ty;
        ty -= this.r * Math.sin(this.dy * Math.PI / 180)
        this.div.style.webkitTransform = "translateX(" + tx + "px) "
            + "translateY(" + ty + "px) "
            + "translateZ(" + tz + "px) "
            + "rotateX("+ this.rx + "deg) "
            + "rotateY("+ this.ry + "deg) ";
    }

2015年6月6日土曜日

Cardboard実験サイト 4.2 Gyro / Cube1 (div構成)

概要
Gyroscopeのデータを取得して、デバイスの移動に応じて画面を動かすサンプルです。

このサンプルではdivで構成した左右二つの画面に視差を付けて3D画像を描画します。


HTML/Cube1のdivを組み合わせて作る立方体を中央に置き、Gyroと連動してCubeを回転させます。感覚的には頭の動きに合わせて視点が動くような感じです。


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


画面レイアウト設定

タグ構造 
<body onload="init();" ontouchmove="blockMove(event)">
    <!-- HTMLL/Cube1と同じ -->
    <div id="container">
      <div id="outerBox">
        <div id="boxR" onclick="restart()">
          <div id="canvasR"></div>
        </div>
        <div id="boxL" onclick="back()">
          <div id="canvasL"></div>
        </div>
      </div>
    </div>
    <!-- Cubeを組み立てる6面のdiv -->
    <div id="divFaces" style="display:none">
        <div id="cube">
            <div class="face" id="f1">One</div>
            <div class="face" id="f2">Two</div>
            <div class="face" id="f3">Three</div>
            <div class="face" id="f4">Four</div>
            <div class="face" id="f5">Five</div>
            <div class="face" id="f6">Six</div>
        </div>
    </div>
</body>


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

javascript
index.html
        var gyro = null;
        function init() {
              //Gyroオブジェクト生成
              gyro = new Gyro();
              //デバイス横位置の大きさに合わせて左右の画面をリサイズ、イベント設定を行う。
              Config.setBoxSizes();
              //視点の設定
              Config.setParspective(4, 0, 500);
             //Cubeオブジェクト追加
              var c1 = Canvas.add(Cube1);
              //タイマーイベントスタート
              Canvas.start(50);
        }
        //スワイプで画面が動かないようにする。
        function blockMove(event) {
              if (Config.isIOS) event.preventDefault();
        }

Cube1.js
//Cubeのコンストラクタを継承
Cube1 = function(parentDiv, side, div) {
            Cube.apply(this, arguments);
        }

        //Cubeのプロトタイプを継承
        Cube1.prototype = new Cube();

        //Canvasのタイマイベントから呼ばれる。アニメ描画。
        Cube1.prototype.move = function() {
            var ry = gyro.ox*2;
            var rx = gyro.oy*2;
            this.div.style.webkitTransform = "translateX(100px) "
                + "translateY(100px) "
                + "rotateX("+ rx + "deg) "
                + "rotateY("+ ry + "deg) ";
        }