情報畑でつかまえてロゴ
本サイトは NTTテクノクロスが旬の IT をキーワードに
IT 部門が今知っておきたい最新テクノロジーに関する情報をお届けするサイトです

JavaScriptでVRコンテンツを面白く - スマホブラウザでお手軽VR 第4回-

VRフレームワークA-Frameを使い 物体をJavaScriptで制御し、アニメーションを加工します。

はじめに

こんにちは。NTTソフトウェアの鈴木雅貴です。ソフト道場 がっつり試し食い!の「スマホブラウザでお手軽VR」コーナー、第4回です。VRも専用機とコンテンツが次々と出ていますが、本連載で対象の、スマホWebブラウザで見られるVRコンテンツにも大きな需要があると考えています。専用機の面倒なセッティングは不要ですし、アプリのインストールも不要。気軽に体験できるというのはやはり強いです。

さて前回ですが、VRフレームワークA-Frameを使い、VR空間にさまざまな物体を配置しました。今回は、物体をJavaScriptで制御し、もうすこしコンテンツを楽しくしてみます。ちなみに、トマトの旬は夏と思われがちですが、日本のような高温多湿はトマトに向いていないため、春から初夏と秋の方が味がよいそうです。このコーナのおかげで教えていただきました。感謝。

2眼VRの年齢制限について

本題に入る前に、大半のVR専用デバイスには年齢制限が設定されています。

機器名対象年齢
PlayStation VR 12歳以上
Oculus Rift 13歳以上
HTC Vive 13歳以上推奨
ハコスコ 7歳以上(2眼)

幼児には目への影響が大きいなどの理由から上記のように設定されているようです。2眼VRのご利用には十分ご注意ください。

JavaScriptで物体を動かす

本題です。今回は、以下をベースに作業を進めていきましょう。前回の物体をアヒルのみにしています(body要素内のみ記載しています)。

<!-- シーンの定義 -->
<a-scene>
<!-- 背景画像 -->
<a-sky src="office.jpg"></a-sky>
<!-- 画像 -->
<a-image src="duck.png" position="0 1 -3"></a-image>
</a-scene>

今回のベース

前回a-animationを使ってアニメーションさせましたが、今回はJavaScriptでやってみましょう。通常のJavaScriptでアニメーションと同じように、属性値を変更させることでできます。A-Frameを読み込んでいるscript要素の下に、以下を追加します。

<script>
document.addEventListener('DOMContentLoaded', function() {
var img = document.querySelector('a-image');

// 物体を回転させる var rotate = function(angle) { // 角度が360以上にならないように if(angle == 358) { angle = 0; } else { angle += 2; } // 次フレームの準備 requestAnimationFrame(rotate.bind(null, angle)); // 属性値を変更して回転させる img.setAttribute('rotation', '0 ' + angle + ' 0'); } rotate(0); }); </script>

a-imagerotation属性の値を、setAttributeを使って変更しています。ここではY軸に沿って回転させています。タイミング調整はrequestAnimationFrameに任せています。requestAnimationFrameについては、MDNのwindow.requestAnimationFrame解説をご覧ください。

ここでは、A-Frame独自のAPIではなく、Web標準技術のものを用いています。このように、A-Frameでも従来と同様にJavaScriptを用いてアニメーションさせることができます。

静止画だとわかりづらいですが、上記により、このように画像が回転します。

JavaScriptで回転

JavaScriptでイベント処理を行う

次は、ユーザの操作に反応するようにしてみましょう。従来のWebコンテンツ同様に、JavaScriptを使うことで、ユーザの操作に対し反応を返すことができます。ユーザの操作に対応するものを「イベント」といいます。A-Frameでは視点を物体に合わせる、というのをイベントとすることができます。

ただ、視点はガイドがないと視覚的にわかりづらいです。そこで、視点に対応する箇所にカーソルを表示させましょう。a-cursorで、リング型をした照準のようなものが表示されます。a-cursora-cameraの中に書きます。

<a-camera>
<a-cursor color="#fff" fuse="true">
</a-cursor>
</a-camera>

このように、視点に対応したカーソルが表示されました。

カーソル表示

では、画像にカーソルを合わせると、画像が大きくなるようにしてみましょう。従来のWebコンテンツ同様、イベントをaddEventListenerしてあげればよいです。A-Frameにおけるカーソル関連のイベントは以下が用意されています。

イベント解説
click 対象がマウス、もしくはfuseでクリックされると発生
mousedown 対象でマウスのボタンが押されると発生
mouseenter カーソルが対象に乗ると発生
mouseleave カーソルが対象から離れると発生
mouseup 対象でマウスのボタンが離されると発生

上記のfuseとは、一定時間対象にカーソルを乗せるとクリックが発生する機能です。デフォルトでは使えませんが、a-cursorfuseプロパティをonにすることで有効にできます。

ここでは、カーソルを合わせると大きくなるということで、mouseenterを使うことにします。script要素の処理にて、var img...の後ろに以下を追加します。

img.addEventListener('mouseenter', function () {
var animation = document.createElement('a-animation');
animation.setAttribute('attribute', 'scale');
animation.setAttribute('to', '3 3 3');
animation.setAttribute('dur', '500');
this.appendChild(animation);
});

mouseenterが発生すると、function(){...}に書かれた処理を実行します。ここでは、カーソルが当たった画像にattribute等を指定したa-animationを子要素として追加して、拡大アニメーションさせるようにしています。

これで、カーソルがあたると大きくなりました。

カーソルで拡大

このように、ユーザの操作に合わせて表示内容を変えることができます。今回は大きくしましたが、要素を追加したり、ということもできます。さらにfuseを使えば、メニューを出して選択したりといったこともできますね。

では、いままでやってきたことを組み合わせて、少々賑やかなものを作ってみましょう。アヒルを複数出して動かしてみます。以下、HTMLです。

アヒルを18羽配置し、カメラを中心として周回させています。自転と上下運動も加えています。加えて、カーソルを合わせると大きくなるようにしています。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>VRサンプル</title>
<!-- A-FrameのライブラリをCDNで読み込む -->
<script src="https://aframe.io/releases/0.3.0/aframe.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
// 物体を回転させる
var rotate = function(img, angle) {
// 角度が360以上にならないように
if(angle > 360) {
angle = 0;
} else {
angle += 0.5;
}
// 次フレームの準備
requestAnimationFrame(rotate.bind(null, img, angle));
// 属性値を変更して回転
img.setAttribute('rotation', '0 ' + angle * 10 + ' 0');
img.setAttribute('position', Math.cos(Math.PI * angle / 180) * 4 + ' ' + (Math.sin(Math.PI * angle * 8 / 180) / 2 + 1.5) + ' ' + Math.sin(Math.PI * angle / 180) * 4);
}

var imgs = document.querySelectorAll('a-image');
for (var i = 0; i < imgs.length; i++) { // カーソルで拡大 imgs[i].addEventListener('mouseenter', function () { this.textContent = null; var animation = document.createElement('a-animation'); animation.setAttribute('attribute', 'scale'); animation.setAttribute('to', '3 3 3'); animation.setAttribute('dur', '500'); this.appendChild(animation); }); imgs[i].addEventListener('mouseleave', function () { this.textContent = null; var animation = document.createElement('a-animation'); animation.setAttribute('attribute', 'scale'); animation.setAttribute('to', '1 1 1'); animation.setAttribute('dur', '500'); this.appendChild(animation); }); rotate(imgs[i], 20 * i); } }); </script> </head> <body> <!-- シーンの定義 --> <a-scene> <!-- 背景画像 --> <a-sky src="office.jpg"></a-sky> <!-- 画像 --> <a-image src="duck.png" position="0 0 0"></a-image> <a-image src="duck.png" position="0 0 0"></a-image> <a-image src="duck.png" position="0 0 0"></a-image> <a-image src="duck.png" position="0 0 0"></a-image> <a-image src="duck.png" position="0 0 0"></a-image> <a-image src="duck.png" position="0 0 0"></a-image> <a-image src="duck.png" position="0 0 0"></a-image> <a-image src="duck.png" position="0 0 0"></a-image> <a-image src="duck.png" position="0 0 0"></a-image> <a-image src="duck.png" position="0 0 0"></a-image> <a-image src="duck.png" position="0 0 0"></a-image> <a-image src="duck.png" position="0 0 0"></a-image> <a-image src="duck.png" position="0 0 0"></a-image> <a-image src="duck.png" position="0 0 0"></a-image> <a-image src="duck.png" position="0 0 0"></a-image> <a-image src="duck.png" position="0 0 0"></a-image> <a-image src="duck.png" position="0 0 0"></a-image> <a-image src="duck.png" position="0 0 0"></a-image>
<!-- 視点表示 --> <a-camera> <a-cursor color="#fff" fuse="true"> </a-cursor> </a-camera> </a-scene> </body> </html>

弊社受付にアヒルのメリーゴーランドが!

アヒルだらけ

今回の最終VRコンテンツはこちらから確認できます。(←クリックでサンプルページが表示されます)

このように、A-Frameでは従来のWebコンテンツ同様、JavaScriptを使うことでページにさまざまな動きを加えることができます。ユーザの動きに反応させるだけで、ずいぶん楽しくなりますね。

A-Frameの詳しい仕様に関しては、A-Frameの公式ドキュメントをご覧ください。

次回予告

次回は、CUIツールを使ってA-FrameのVR空間を作ってみる予定です。空気も乾燥してきましたので、喉や皮膚にも気を配りつつお過ごしください。

著者プロフィール
鈴木 雅貴
鈴木 雅貴
作品公開の場としてのWebに可能性を感じ入社。 XML関連業務や継続的インテグレーション社内普及活動などを経て、 2013年より新たに設立されたHTML5推進室の主要メンバーとしてWeb技術を推進している。 セミナーでの講演や書籍執筆などの活動も行っている。 著書に『HTML5プロフェッショナル認定試験 レベル1 対策テキスト&問題集』(マイナビ/共著)。得意領域はCSS。 調理歴20年超。本人も原因不明のアヒル好き。