A-FrameであっけなくWebXRができちゃった件

# はじめに

近年さまざまなVRヘッドセットが発売され、より一層仮想世界と我々の現実世界との距離が近くなった。そして、Meta Quest3 や Apple Vision Pro が発売され複合現実(MR)といった新たな体験が提供されるようになった。

https://www.meta.com/jp/quest/quest-3/

https://www.apple.com/jp/apple-vision-pro/

WebXR機器APIを使用すると、PC や XR (VR、AR、MRを含めた技術の総称) デバイス上でブラウザを通し、XRコンテンツやアプリが使用できるそう。
さっそく試してみた。

# WebXRとは
WebXRに関する基本概念やAPIの説明は以下のページに詳しく記載されていた。

https://developer.mozilla.org/ja/docs/Web/API/WebXR_Device_API/Fundamentals

# 実行環境

- VSCode
    - Live Server: 5.7.9

https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer

- A-Frame: 1.6.0

https://aframe.io/docs/1.6.0/introduction/


A-FrameはWebXRコンテンツを容易に作成できるフレームワーク。
HTMLベースのコンポーネントを利用しているのでWeb開発者にとって扱いやすく、JavaScriptを使用してカスタムコンポーネントを作成できるため拡張性にも優れている。

# 実装

## HTMLファイルに直接実装

A-Frameは何もインストールせずにプレーンなHTMLファイルから開発できるとのことなので、とりあえず VSCode でHTMLファイルを作成しA-Frameのドキュメントの「導入」にあるコードをコピペ。
Live Serverでローカル実行してみた。

<details><summary>index.html</summary>

```html
<!DOCTYPE html>
<html>
	<head>
		<script src="https://aframe.io/releases/1.6.0/aframe.min.js"></script>
	</head>
	<body>
		<a-scene>
			<a-box position="-1 0.5 -3" rotation="0 45 0" color="#4CC3D9"</a-box>
			<a-sphere position="0 1.25 -5" radius="1.25" color="#EF2D5E"></a-sphere>
            <a-cylinder position="1 0.75 -3" radius="0.5" height="1.5" color="#FFC65D"></a-cylinder>
			<a-plane position="0 0 -4" rotation="-90 0 0" width="4" height="4" color="#7BC8A4"></a-plane>
            <a-sky color="#ECECEC"></a-sky>
		</a-scene>
	</body>
</html>
```
</details>

![A-Frame_start.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3635206/f7610b4a-f35c-f689-c7af-1c3155b4c9e2.png)

これだけで、ブラウザ上でVRコンテンツを使用できた。
内容を細かく見ていくと・・・

```html
<script src="https://aframe.io/releases/1.6.0/aframe.min.js"></script>
```

\<script> タグで A-Frame バージョン 1.6.0 を呼び出している。
<br>


```html
<a-scene>
    <a-box position="-1 0.5 -3" rotation="0 45 0" color="#4CC3D9"></a-box>
    <a-sphere position="0 1.25 -5" radius="1.25" color="#EF2D5E"></a-sphere>
    <a-cylinder position="1 0.75 -3" radius="0.5" height="1.5" color="#FFC65D"></a-cylinder>
    <a-plane position="0 0 -4" rotation="-90 0 0" width="4" height="4" color="#7BC8A4"></a-plane>
    <a-sky color="#ECECEC"></a-sky>
</a-scene>
```

\<a-scene> タグで A-Frame のシーンを定義し、この中に3Dオブジェクトが配置されている。

| オブジェクト| タグ | オプション |
| :---:| :--- | :--- |
| 立方体 | \<a-box> | position="-1 0.5 -3" <br>　立方体の位置をX軸で-1、Y軸で0.5、Z軸で-3に設定<br>rotation="0 45 0" <br>　立方体をY軸（上下軸）周りに45度回転<br>color="#4CC3D9" <br>　立方体の色を水色に設定 |
| 球体 | \<a-sphere> | radius="1.25" <br>　球体の半径を1.25に設定 |
| 円柱 | \<a-cylinder> | radius="0.5"<br>height="1.5" <br>　円柱の半径を0.5、高さを1.5に設定 |
| 平面 | \<a-plane> | rotation="-90 0 0" <br>　平面をX軸周りに-90度回転させ、地面に対して水平<br>width="4"<br>height="4" <br>　平面の幅と高さをそれぞれ4に設定 |
| 背景(空) | \<a-sky> | color="#ECECEC"<br>　背景の色を薄いグレーに設定 |

ただし、このままではブラウザ全体に表示されるのでページに埋め込むようしたい。

## ページ内への埋め込み

どうやら、A-Frameのシーンを含むHTMLファイルとメインのHTMLファイルに分けて作成し、メインのHTMLファイルに\<iframe> タグを追加するとできるそう。

ひとまず、以下2つのファイルを作成。
- **index.html** (メインのHTMLファイル)
- **vr_scene.html** (A-Frameのシーンを含むHTMLファイル)
<br>
vr_scene.html は、さっき作成したHTMLファイルの名前を変更したもの。

index.html の中身は以下の通り。

```html
<!DOCTYPE html>
<html lang="ja">
	<head>
		<meta charset="UTF-8" />
		<title>VR Scene</title>
	</head>
	<body>
		<h1>A-Frameのシーンを埋め込む</h1>
		<p>「vr_scene.html」で作ったA-Frameのシーンが埋め込まれている。</p>
		<iframe src="vr_scene.html" width="600" height="400" frameborder="0"></iframe>
	</body>
</html>
```

\<iframe> タグの src で vr_scene.html を指定。width と height でサイズを指定、frameborder は枠線の太さを指定できる。

実際のページは以下の画像の通り。

![A-Frame_埋め込み.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3635206/f8439506-117c-dc23-5d23-ad445163bc8e.png)

CodoPen でも実装できた。wasd キーで仮想空間内を自由に移動できる。

<p class="codepen" data-height="500" data-default-tab="result" data-slug-hash="YzoOqoM" data-pen-title="vr_scene" data-user="tosimitsu-the-builder" style="height: 500px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/tosimitsu-the-builder/pen/YzoOqoM">
  vr_scene</a> by tosimitsu (<a href="https://codepen.io/tosimitsu-the-builder">@tosimitsu-the-builder</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

# おわりに
手軽にWebサイトにVRコンテンツを追加できることがわかった。
Webサイトで読者に伝えたい内容によっては、360度画像などのコンテンツを使った方が効果的に場の情報を伝えることができそう。

ただし、\<iframe> で読み込んだコンテンツはページのコンテンツと評価されないので、あまりに多様するとページ量の割に情報が無い低品質なページとみなされてSEO効果は薄れるかも:weary:


VRゴーグルを使うと、より仮想空間を体験できそうなので試してみたい。
気が向いたら、Webアプリに組み込んでVR用のアプリ開発にも着手してみようと思う。