みなさん名刺は持っていますか?
もっているそこのあなた、まさか紙の名刺なんていう時代遅れなものじゃありませんよね?(言い過ぎ)
時代はAR/VRです、名刺もAR化しちゃいましょう!
というわけでAR空間で見る名刺「AR名刺」を作りました。
紙の名刺と違って動きがつけれるので、人それぞれ特有の自分名刺をつくることができます。
AR名刺がどんなものか分からない方はこちらをご覧ください。
最近はARKitを使って誰でも簡単にネイティブのARアプリを作れるようになっています。
しかし今回はブラウザ上で動くWebアプリとして作っています。
Webアプリである利点として、インストールの手間がなく、URLを開きさえすれば楽しめるという点があります。
名刺という性質上そんなに長く遊ぶものでもないため、サクッと遊んでもらうにはWebアプリが適しているというわけです。
ではブラウザで動くAR名刺を手順を順に説明していきます!
(将来ハンズオンをすることを見越してハンズオン風に書いています。github)
必要な知識
- HTML:動かすだけならHTMLのみで十分です。
- Javascript:タップ動作などを追加するなど応用的なことをする際にが必要となります。
フレームワーク・ライブラリ
- A-Frame:VR用のフレームワークです。AR空間内にオブジェクトを表示させるコードも、こちらのフレームワークに従って記述します。
- AR.js(v0.9.0):A-FrameをAR用に変換した、マーカーベースARのライブラリです。マーカーベースARとは、画像などの何らかのマーカーをカメラで認識すると、マーカー上にオブジェクトが表示されるタイプのARです。v0.8からv0.9にかけて一部の記法が新しくなっているので注意してください。
Step1:マーカー上にオブジェクトを表示させる
いきなりコードをドンッと。
<!DOCTYPE html>
<html>
<head>
<script src='https://aframe.io/releases/0.9.2/aframe.min.js'></script>
<script src='https://raw.githack.com/jeromeetienne/AR.js/2.0.8/aframe/build/aframe-ar.js'></script>
</head>
<body style='margin: 0px; overflow: hidden;'>
<!-- debugUIEnabledをtrueにすると、デバッグ情報が表示される。 -->
<a-scene embedded arjs='debugUIEnabled: false;'>
<!-- マーカーを設定。デフォルトではpresetにhiroとkanjiが設定可能。 -->
<a-marker preset="hiro">
<!-- 立方体を描画 -->
<a-box position='0 0.5 0' material='color: yellow;'></a-box>
</a-marker>
<a-entity camera></a-entity>
</a-scene>
</body>
</html>
こちらのコードをどこかにホスティングし、スマホで開いてください(面倒くさい方はこちらから)。
するとカメラを起動するか聞かれるので、許可してください。
カメラで下のHiro画像を見てみると・・・?
黄色い箱が画像の上に現れたでしょうか?
ARなのでマーカーを認識できる限り側面等を見ることができます。
出てこない方はマーカーに光の反射等がないようにして見るようにしてみてください。
端末によって出なかったりする場合もあるようです。
コードの解説
おまじない
<!DOCTYPE html>
<html>
<head>
<script src='https://aframe.io/releases/0.9.2/aframe.min.js'></script>
<script src='https://raw.githack.com/jeromeetienne/AR.js/2.0.8/aframe/build/aframe-ar.js'></script>
</head>
<body style='margin: 0px; overflow: hidden;'>
<!-- debugUIEnabledをtrueにすると、デバッグ情報が表示される。 -->
<a-scene embedded arjs='debugUIEnabled: false;'>
・・・中略・・・
</a-scene>
</body>
</html>
こちらはいわゆるおまじない的な部分ですね。そのまま書いちゃいましょう。
マーカー
<!-- マーカーを設定。デフォルトではpresetにhiroとkanjiが設定可能。 -->
<a-marker preset="hiro">
・・・中略・・・
</a-marker>
こちらはオブジェクトを表示させるためのマーカーの設定です。
presetとして先程使ったhiroと、もう一つkanjiがあります。
自分で好きなマーカーを設定することもできます(後でやります)。
<a-marker>
の間にARで表示するオブジェクトを書いていきます。
オブジェクト
<!-- 立方体を描画 -->
<a-box position='0 0.5 0' material='color: yellow;'></a-box>
Step1では<a-box>
を使って立方体を描画しています。
A-Frameで用意されている図形は利用できます。
こちらの左サイドバーのPRIMITIVES以下を参照してください(一部図形でないものも含みます)。
position
でオブジェクトを表示する位置をします。
3つの値はそれぞれx、y、z軸を指し、それぞれマーカーを真上から見たときに右、手前、下方向が正の方向となります(下図参照)。
y=0だとマーカーの表面にオブジェクトが描画され干渉しあって汚くなるので、0.5だけ浮かして表示しています。
Step2:オブジェクトにアニメーションをつける
Step1でオブジェクトを表示させることができたので、次に回転などのアニメーションをつけてみましょう。
<body>
の内側を以下のように変更します。
<script>
// a-sceneより先に宣言する必要あり
AFRAME.registerComponent('marker', {
init: function () {
// マーカー検出時にアニメーション開始
let marker = this.el;
marker.addEventListener('markerFound', function () {
document.getElementById('obj').setAttribute('animation__scale', 'enabled: true');
});
}
});
</script>
<a-scene embedded arjs='debugUIEnabled: false;'>
<a-marker preset='hiro' marker>
<!-- 三角錐を描画 -->
<!-- 最初の3秒で大きさの倍率を0から1に -->
<!-- その後3秒かけてxyz軸方向それぞれ360度回転をループ -->
<a-tetrahedron id='obj' material='color: red;' position='0 1.5 0' scale='0 0 0'
animation__scale='property: scale; dur: 3000; from: 0 0 0; to: 1 1 1; easing: linear; enabled: false;'
animation__rotation='property: rotation; dur: 3000; from: 0 0 0; to: 360 360 360; easing: easeInOutCubic; loop: true; startEvents: animationcomplete__scale;'
>
</a-tetrahedron>
</a-marker>
<!-- カメラを設定 -->
<a-entity camera></a-entity>
</a-scene>
お試しだけしたい方はこちらから。
マーカーは同じくhiroです。
Step2では三角錐を表示させます。
またアニメーションとして、はじめの3秒で大きさの倍率を0から1にし、その後3秒かけてxyz軸をそれぞれ一定角度回転させることを繰り返します。
コードの解説
マーカーの検出
<script>
// a-sceneより先に宣言する必要あり
AFRAME.registerComponent('marker', {
init: function () {
// マーカー検出時にアニメーション開始
let marker = this.el;
marker.addEventListener('markerFound', function () {
document.getElementById('obj').setAttribute('animation__scale', 'enabled: true');
});
}
});
</script>
アニメーションはデフォルトではページを読み込んだ時点から開始してしまうため、いざマーカーを認識したときにはアニメーションが途中だったり終わっていたりという可能性があります。
なので、マーカーが読み込まれた瞬間からアニメーションを開始するロジックをここに書いています。
マーカーにはイベントとしてmarkerFound
とmarkerLost
が用意されています。
markerFound
が発火したときにアニメーションを開始(有効化)するようにしています。
アニメーション
<a-tetrahedron id='obj' material='color: red;' position='0 1.5 0' scale='0 0 0'
animation__scale='property: scale; dur: 3000; from: 0 0 0; to: 1 1 1; easing: linear; enabled: false;'
animation__rotation='property: rotation; dur: 3000; from: 0 0 0; to: 90 180 360; easing: easeInOutCubic; loop: true; startEvents: animationcomplete__scale;'
>
</a-tetrahedron>
<a-tetrahedron>
は三角錐のオブジェクトです。
アニメーションはanimation
またはanimation__name
という属性をつけることで追加できます。
property
はアニメーションの種類です。
ここでは大きさの倍率のscale
と軸回転のrotation
を使っています。
dur
はアニメーションの継続時間です。
単位はミリ秒です。
from
、to
はアニメーションを開始時、終了時の状態を表します。
scale
では3軸ともに倍率を0から1に、rotation
では3軸順に0度から90, 180, 360度回転させています。
easing
ではアニメーションの加速度を設定します。
A-Frameで用意されているものはこちらから確認できます。
easingそのものについてはこちらでわかりやすい解説が行われています。
今回はscale
では終始同じ速度で動くものを、rotation
では初めと終わりは速度が早く、真ん中は遅いものを使っています。
アニメーションの再生のタイミングの設定方法は主に2つあります。
- 何も設定しない。ページの読み込みと同時にアニメーションが開始します。
- 他のアニメーションの終了を検知して開始する。
scale
では1が、rotation
では2が用いられています。
scale
は最初のアニメーションですが、マーカーが認識されるまで開始して欲しくありません。
そこでenabled
をfalse
に設定することで、アニメーションを無効化し、マーカーが認識されたときにjsでこの値をtrue
に変更しています。
rotation
はscale
のアニメーションが終わり次第開始させます。
startEvents
に監視したいアニメーションの名前を入れたanimationcomplete__name
を指定することで、連続的にアニメーションを発火させることができます。
注意点として、アニメーションの名前は同じオブジェクトの中のものしか参照できません。
違うオブジェクトのアニメーションを監視したい場合は別途jsを書く必要があります。
loop
をtrue
にすることで、アニメーションが繰り返されます。
アニメーション開始時の状態は終了時の状態に関わらず、from
に設定した状態にリセットされます。
他のproperty
などアニメーションのドキュメントを確認したい方はこちらをご覧ください。