コンテンツにスキップ

Top

RICOH THETA などの360度カメラをブラウザに表示させる方法

いろいろあるが簡単な A-Frame というのを使う。

これは360度画像を表示させるライブラリというよりもAR全般の機能を提供してくれているのでくそほどでかいが、360度画像を自身のホームページに埋め込む程度なら以下でちゃちゃっとできるのですごい便利。

ライセンスもMIT Licenseなので商用でも気軽に使える。

360度画像も(おそらく)規格があるのでRICOH THETAだけじゃなくいろんなハードでとった360度画像も基本的には表示できる。

サンプル

以下のようなHTMLでもう出来上がり。

index.html

<html>
  <head>
    <script src="https://aframe.io/releases/1.3.0/aframe.min.js"></script>
  </head>
  <body>
    <div style="width:672px;height:336px">
      <a-scene embedded>
        <a-sky src="./pixage_panorama01.jpg" rotation="0 -130 0"></a-sky>
      </a-scene>
    </div>
  </body>
</html>

index.htmlと同一のフォルダに pixage_panorama01.jpg をおいてくれればOK。

出来上がりは以下。そのままでも動かせるが、右下のVRというボタンを押下したら全画面表示になる。

この元画像は、以下のサイトのサンプルをお借りした。
360度パノラマ画像サンプル

タイトル

なんか横に広がってる変な感じのjpgで、これがA-Frameライブラリで加工されると360度画面操作が可能になるの不思議。

マウスでズームイン、ズームアウトをしたい

ここを参考にしたけど全然うまくいかないんでアバババと思ってたけどactiveをtrueにしたら行けた。

<html>
  <head>
    <script src="./aframe.min.js"></script>
  </head>
  <body>
    <div style="width:672px;height:336px">
      <a-scene embedded>
        <a-entity id="cam" camera="zoom: 1, active: false" look-controls="reverseMouseDrag: true"></a-entity>
        <a-sky src="./pixage_panorama01.jpg" rotation="0 -130 0"></a-sky>
      </a-scene>
    </div>
  </body>
</html>
<script>
  window.addEventListener("wheel", (event) => {
    const delta = event.wheelDelta / 120 / 10;
    var mycam = document.getElementById("cam").getAttribute("camera");
    var finalZoom = document.getElementById("cam").getAttribute("camera").zoom + delta;
    if (finalZoom < 0.5) finalZoom = 0.5;
    if (finalZoom > 2) finalZoom = 2;
    mycam.zoom = finalZoom;
    mycam.active = true;
    document.getElementById("cam").setAttribute("camera", mycam);
  });
</script>

mycam.active = true; を追加するのが味噌。

以上!

と言いたいところだけど、上記を実装したところ、常にマウスの上下を拾ってしまい、ページの上下スクロール時に邪魔になることに気づいた。

なので、フルスクリーンの時だけ(vrボタンを押して全画面表示になっている時だけ)マウスイベントを拾ってズームイン・ズームアウトするように改良。

<html>
  <head>
    <script src="./aframe.min.js"></script>
  </head>
  <body>
    <div style="width:672px;height:336px">
      <a-scene embedded>
        <a-entity id="cam" camera="zoom: 1, active: false" look-controls="reverseMouseDrag: true"></a-entity>
        <a-sky src="./pixage_panorama01.jpg" rotation="0 -130 0"></a-sky>
      </a-scene>
    </div>
  </body>
</html>
<script>
  window.addEventListener("wheel", (event) => {
    if(isFullScreen()){
      const delta = event.wheelDelta / 120 / 10;
      var mycam = document.getElementById("cam").getAttribute("camera");
      var finalZoom = document.getElementById("cam").getAttribute("camera").zoom + delta;
      if (finalZoom < 0.5) finalZoom = 0.5;
      if (finalZoom > 2) finalZoom = 2;
      mycam.zoom = finalZoom;
      mycam.active = true;
      document.getElementById("cam").setAttribute("camera", mycam);
    }
  });
  function isFullScreen() {
    if ((document.fullscreenElement              !== undefined && document.fullscreenElement              !== null) ||
        (document.mozFullScreenElement           !== undefined && document.mozFullScreenElement           !== null) ||
        (document.webkitFullscreenElement        !== undefined && document.webkitFullscreenElement        !== null) ||
        (document.webkitCurrentFullScreenElement !== undefined && document.webkitCurrentFullScreenElement !== null) ||
        (document.msFullscreenElement            !== undefined && document.msFullscreenElement            !== null) ){
      return true;
    } else {
      return false;
    }
  }
</script>

んで、完成版が以下。

これでVRを押して全画面にした時だけマウスカーソルでズームイン/ズームアウトするようになる!

VRボタン消したい

VRボタンを消すのは簡単。vr-mode-uiという属性があるので、

<a-scene embedded vr-mode-ui="enabled: false">

とすればいいだけ。

VRボタンを変更したい

VRってボタンいやら!!

って思ってるなら変えることはできるけどめんどい。

https://aframe.io/docs/1.3.0/components/vr-mode-ui.html

に書いてある方法で変更はできるが、(実際はz-indexを指定しないとダメ)

結局のところ自分でリンクボタン作んなきゃいけないってこと。

<a-scene embedded  vr-mode-ui="enterVRButton: #myEnterVRButton;">
  <a-sky src="./pixage_panorama01.jpg" rotation="0 -130 0"></a-sky>
  <button id="myEnterVRButton" type="button" style="z-index: 100; position: fixed;">自作VR!</button>
</a-scene>

(z-indexとpositionの指定しないと画像の後ろに隠れてボタン見えなくなるから注意)

なお、当然だがbuttonじゃなくてリンク(a)も可能。

以上!

似たような機能として https://pannellum.org/ というのがあるので今後はこっちみとく。

this immersive website requires access to your device motion sensors

PCのブラウザから見たらいい感じだったのに、iPhoneだと以下のようなダイアログがでて許可しないと動かせなかった。
iOS12.2ぐらいからそうらしい。

タイトル

てっきりブラウザとかスマホの制限かと思ったらA-Frameが出してるとのこと。

なので以下の device-orientation-permission-ui 属性をa-sceneに追加すればでなくなる。

<a-scene device-orientation-permission-ui="enabled: false">
</a-scene>

けど動かなくもなるのでやめたほうがいい。

12.xぐらいまでは

設定→Safari→モーションと画面の向きのアクセス を有効にすればでなくなるし、そもそもこのダイアログもでなかたらしいけど、13以降はモーションと画面の向きのアクセス設定がなくなって、上記のダイアログで許可をださないといけないみたい。

なんだろうね。面倒くさい。Androidは特に問題はないけど。

iPhone で VR が有効にならない

ちなみにスマホ上では指やマウスで動かすのではなく、デバイスのモーションで動くようになる。

VRメガネをつけて使用するイメージをすればわかりよいが、スマホ本体の上下左右にあわせて画面が移動する。

上記のダイアログでAllowを押せばiPhoneでも動くのだが、VRボタンを押して全画面表示にすると、以下のダイアログがでて、以降動かない。

Insert phone into Cardboard holder.
タイトル

なんじゃこりゃ。

なお、Androidでは問題なく動いている。iPhoneはどうしようもないな、と言いたいところだが、Andoroidだっていつまで動くのか。

Webサーバ上で確認しないと真っ白になる

index.htmlを直接ダブルクリックしても表示されない(真っ白画面になる)ので注意。

あくまでWebサーバ上で実行すること。

Webサーバの準備が面倒なら、npmのhttp-serverを使うと楽ちん。

index.htmlがある場所で、

npx http-server

と実行すれば簡易サーバが立ち上がるので簡単に確認できる。

a-scene に embedded をつけないと全画面表示になる

<div>でwidthとか指定してるのに全画面表示になって困る、という場合。

a-scene タグに embedded とつけていないケースが多いので注意。

VRボタンの変更はめんどい

VRってボタンいやら!!

って思ってるなら変えることはできるけどめんどい。

https://aframe.io/docs/1.3.0/components/vr-mode-ui.html に書いてある方法で変更はできるが、(実際はz-indexを指定しないとダメ)

結局のところ自分でリンクボタン作んなきゃいけないってこと。

<a-scene embedded  vr-mode-ui="enterVRButton: #myEnterVRButton;">
  <a-entity id="cam" camera="zoom: 1, active: false" look-controls="reverseMouseDrag: true"></a-entity>
  <a-sky src="./pixage_panorama01.jpg" rotation="0 -130 0"></a-sky>
  <button id="myEnterVRButton" type="button" style="z-index: 100; position: fixed;">自作VR!</button>
</a-scene>

z-indexとpositionの指定しないと後ろに隠れてボタン見えないから注意。なお、ボタンじゃなくて当然だがリンクも可能。

以上!