JavaScriptでVRコンテンツを面白く - スマホブラウザでお手軽VR 第4回-
VRフレームワークA-Frameを使い 物体をJavaScriptで制御し、アニメーションを加工します。
ソフト道場のがっつり試し食い!
- 2016年11月02日公開
はじめに
こんにちは。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-image
のrotation
属性の値を、setAttribute
を使って変更しています。ここではY軸に沿って回転させています。タイミング調整はrequestAnimationFrame
に任せています。requestAnimationFrameについては、MDNのwindow.requestAnimationFrame解説をご覧ください。
ここでは、A-Frame独自のAPIではなく、Web標準技術のものを用いています。このように、A-Frameでも従来と同様にJavaScriptを用いてアニメーションさせることができます。
静止画だとわかりづらいですが、上記により、このように画像が回転します。
JavaScriptでイベント処理を行う
次は、ユーザの操作に反応するようにしてみましょう。従来のWebコンテンツ同様に、JavaScriptを使うことで、ユーザの操作に対し反応を返すことができます。ユーザの操作に対応するものを「イベント」といいます。A-Frameでは視点を物体に合わせる、というのをイベントとすることができます。
ただ、視点はガイドがないと視覚的にわかりづらいです。そこで、視点に対応する箇所にカーソルを表示させましょう。a-cursor
で、リング型をした照準のようなものが表示されます。a-cursor
はa-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-cursor
のfuse
プロパティを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年超。本人も原因不明のアヒル好き。