どんなアプリ?
おおもとの記事です。
【Django,A-frame】お店探しのWebARを作りました。
対象の読者
一応、下記前提で記事を書いていきますが、難しいことは書いてないので分からない用語があれば調べてください。
(私も初心者なので、間違った内容を書いていたらご指摘いただければ幸いです)
- HTMLの初歩的な用語、文法を知っている人向け
- javascriptの初歩的な用語、文法を知っている人向け
今回の内容
A-frameでオブジェクトを特定の方向に表示
A-frameで画面タッチでオブジェクトを表示
A-frameとは
HTMLで簡単にARを実装できるThree.jsをベースに開発されたWebフレームワークです。
A-frame専用のタグをbodyの中に入れるだけでARが実装できます。例えばa-cameraタグを入れればカメラ映像、a-planeを入れれば平面オブジェクトがWeb上に映し出されます。
基本的な使い方は下記サイトが参考になります。
https://bagelee.com/programming/aframe-creative-coding/
A-frameでオブジェクトを特定の方向に表示
今回、LocationBasedARと呼ばれる特定の場所にARを表示する手法を使いました。
特定の緯度経度にある程度近づいた時にARが表示されます。
参考サイト
https://bagelee.com/programming/location-based-ar/
- entityでブロック化する
a-entityタグはdivと同じようなもので、表示空間のブロック化をしてくれます。a-entityの中に記述されたコードは親であるa-entityの属性を引き継ぎます。 - gps-entity-place属性で表示する緯度軽度を設定する
a-entityの属性にgps-entity-place="latitude: 緯度; longitude: 経度;"と記載することで、その場所にオブジェクトを表示することができます。 - オブジェクトの表示
今回は日本語のテキストを表示したかったのですが、A-frameにはa-textタグがあり文字を表示できるのですが、残念ながら日本語テキストに対応していないため、canvasで日本語テキストを画像化しました。a-imageで画像を表示させることで代用しています。
scaleはオブジェクトのサイズを指定できます。今回は距離に合わせてサイズを変えたかったので、取得した緯度経度から現在地との距離を算出し、距離に反比例した大きさになるようにしています。 - htmlに反映
html上で反映したい箇所に新たにa-entityを作成して、document.querySelector(id名).innerHTMLで1〜3で記述した内容を反映します。
document.querySelector('#test'+shop_cnt).innerHTML = `
<a-entity gps-entity-place="latitude: ${(shop_lat)}; longitude: ${(shop_lng)};">
<a-image
scale="${(width)/_size} ${height/_size} 1" src="${base64}"
look-at="[gps-camera]"
>
</a-image>
・・・
</a-entity>
`
・・・
<a-entity id="test0" position="0 40 0"></a-entity>
<a-entity id="test1" position="0 20 0"></a-entity>
<a-entity id="test2" position="0 0 0"></a-entity>
<a-entity id="test3" position="0 -20 0"></a-entity>
<a-entity id="test4" position="0 -40 0"></a-entity>
・・・
A-frameで画面タッチでアクションの実行
まず前提として、A-frameはカーソルと呼ばれる視線が存在します。視線はカメラの中央から一直線に伸びていて、それがオブジェクトに交差(raycaster)することで空間のオブジェクトに干渉することができます。
1.タッチすることができるオブジェクトを設定する
raycasterは交差できるオブジェクトの指定します。下の場合はclassがclickableになっているオブジェクトが交差できるようになっています。
<a-camera
・・・
raycaster="objects: .clickable"
cursor="rayOrigin: mouse">
・・・
<a-sphere class="clickable" material="side: back" visible="false" position="0 -0.1 -1" foo></a-sphere>
2.オブジェクトがタッチされた時の処理
オブジェクト名(ここではfoo)をregisterComponentで呼び出し、中身に処理を入れます。
ここではタッチされた時に(mouseup)、visibleをTrue/False切り替えしてオブジェクトの表示/非表示をします。
<script>
AFRAME.registerComponent("foo", {
init: function() {
this.el.addEventListener("mouseup", e => {
var showflg = document.getElementById("modalOpen").getAttribute('visible');
if(String(showflg) == 'true'){
document.getElementById("modalOpen").setAttribute('visible','false');
}
else{
document.getElementById("modalOpen").setAttribute('visible', 'true');
}
})
}
});
</script>