やったこと
認証機能を持つサイトを作り、ログインするとクリスマスツリーが表示されるサイトを作りました。
できたもの
- ログインするとクリスマスツリーが表示されます。
ホントはツリーに、ログインユーザーのアカウント名を表示したかったのですが出来ませんでした。- 2019/12/13 追記
- ログインユーザーのアカウント名表示できました。アカウント名を取得して3Dオブジェクトとしてツリーの隣に配置しました。
ちょっと改良。ツリーの隣にログオンユーザーのアカウント名(JjjJ j4amountain)と、Merry Christmasの文字を追加 pic.twitter.com/Dslqfa3756
— j4amountain (@zsipparu) December 12, 2019
参考
-
超初心者がAuth0でログイン機能を実装した
- Auth0を使用したシングルページの認証サイトの作成方法を参考にさせて頂きました。
-
WebVRフレームワークA-Frameで、雪降る街の景色を作ってみました
- クリスマスツリーのソースをお借りしました。
ソース
- Auth0のサンプルを改良したindex.htmlファイルをgithubに置きました。
-
https://github.com/zgw426/Christmastree2019
- index-r1.html : クリスマスツリーのみ
- index-r2.html : +アカウント名
作り方
Auth0でシングルページの認証サイトのアプリケーション登録し、登録したアプリケーションのQuick Start
にあるサンプルをダウンロードします。
ダウンロードしたサンプルにあるindex.html
ファイルを更新して、クリスマスツリーを追加しました。クリスマスツリーは、A-Frame
というhtmlで3Dオブジェクトを生成できるスクリプトを使用しました。
1.クリスマスツリーの追加
作成したindex.htmlは、githubのindex-r1.html
です。
ここでは、ベースのindex.htmlからの変更点を紹介します。
1-1.A-Frameのモジュールをロード処理を追加
A-Frameのモジュールaframe.min.js
をロードします。
<script src="https://aframe.io/releases/0.8.0/aframe.min.js"></script>
別バージョンのモジュールをロードすると正常に処理が実行されない場合があるので注意ください。以下のモジュールを指定した場合、カメラワークの処理(カメラがツリーの周りをまわる)が停止しました。
<script src="https://aframe.io/releases/0.9.2/aframe.min.js"></script>
1-2.3Dオブジェクトを追加
A-Frameは、A-Frameが用意したタグを<a-scene>・・・</a-scene>
の間(・・・のところ)に記載することで3Dオブジェクトが描画されます。簡単ですね。(<a-scene>
もA-Frameのタグです)
<a-scene id="viewport"
data-range="60 8 60">
<a-entity>
<a-animation attribute="rotation"
from="0 0 0" to="0 360 0"
dur="72000" easing="linear"
repeat="indefinite"
>
</a-animation>
<a-plane id="ground"
rotation="-90 0 0"
width="200" height="200"
material="shader: flat; color: #f0f0f0"
>
</a-plane>
<a-sky id="sky" color="#040d1a"></a-sky>
<a-entity id="tree_christmas" scale="4 4 4">
<a-animation attribute="rotation"
from="0 360 0" to="0 0 0"
dur="72000" easing="linear"
repeat="indefinite"
>
</a-animation>
<a-entity id="tree_xmas_parts"
position="0 1 0">
<a-entity id="xmas_parts1">
<a-box material="color:#4cca10" geometry="" position="-0.04 1.374 -0.284" scale="1 0.793 1"></a-box><a-box material="color:#4cca10" position="0.044 0.844 0.53" scale="1 0.43 1"></a-box><a-box material="color:#4cca10" position="-0.876 0.932 -0.275" scale="1.172 0.556 1" geometry=""></a-box><a-box material="color:#4cca10" position="-1.278 0.527 -0.275" scale="1.172 0.556 1"></a-box><a-box material="color:#4cca10" position="1.016 1.023 0" scale="1.063 0.59 1" geometry=""></a-box><a-box material="color:#4cca10" position="0.361 0.361 -0.47" scale="1.561 0.491 1"></a-box><a-box material="color:#4cca10" position="0.085 0.841 -0.977" scale="1.561 0.575 1"></a-box>
<a-box id="node1" material="color:#a44523"></a-box>
</a-entity>
<a-entity id="xmas_parts2" position="-0.456 1.709 -0.266" rotation="0 -156.704 0">
<a-box material="color:#4cca10" position="-0.216 1.161 -0.359" scale="1 0.618 0.773"></a-box><a-box material="color:#4cca10" position="0.044 0.844 0.53" scale="1 0.43 1"></a-box><a-box material="color:#4cca10" position="-0.876 0.675 -0.275" scale="1.172 0.556 1"></a-box><a-box material="color:#4cca10" position="-1.064 0.527 -0.722" scale="1.172 0.556 1" geometry=""></a-box><a-box material="color:#4cca10" position="-0.031 0.205 -0.686" scale="1.172 0.556 1" rotation="0 -39.99245410013146 0"></a-box><a-box material="color:#4cca10" position="0.697 1.023 -0.137" scale="1.063 0.59 1"></a-box><a-box material="color:#4cca10" position="0.6 0.361 0.6" scale="1.231 0.491 1" rotation="0 -40.90918657234078 0"></a-box><a-box material="color:#4cca10" position="0.761 0.406 -0.435" scale="1.231 0.491 1"></a-box><a-box material="color:#4cca10" position="0.451 -0.396 -0.942" scale="1.231 0.491 1"></a-box><a-box material="color:#4cca10" position="-0.579 1.237 0.567" scale="0.894 0.329 0.573"></a-box>
<a-box id="node2" material="color:#a44523" position="-0.181 0 -0.28" rotation="0 -13.349916626548183 0" scale="0.912 1.313 1"></a-box>
</a-entity>
<a-entity id="xmas_parts3" position="-0.456 3.408 -0.345" rotation="0 -172.575 0">
<a-box material="color:#4cca10" position="-0.26 1.374 -0.278" scale="0.613 0.631 0.432" geometry=""></a-box><a-box material="color:#4cca10" position="0.223 1.023 -0.532" scale="0.613 0.631 0.432"></a-box><a-box material="color:#4cca10" position="0.319 0.844 0.168" scale="0.656 0.43 0.514" rotation="0 -29.621918008263563 0"></a-box><a-box material="color:#4cca10" position="-0.224 0.932 -0.029" scale="0.761 0.556 0.609" rotation="0 -21.772396214971284 0" geometry=""></a-box><a-box material="color:#4cca10" position="-0.462 0.932 -0.665" scale="0.616 0.456 0.609" rotation="0 -124.15995420484938 0"></a-box><a-box material="color:#4cca10" position="-0.905 0.527 -0.555" scale="0.897 0.556 0.665" geometry=""></a-box><a-box material="color:#4cca10" position="-0.456 0.209 0.013" scale="0.897 0.43 0.665"></a-box><a-box material="color:#4cca10" position="0.382 0.722 -0.373" scale="1.063 0.411 0.719"></a-box><a-box material="color:#4cca10" position="0.775 0.376 -0.34" scale="0.897 0.381 0.517" geometry=""></a-box><a-box material="color:#4cca10" position="0.413 -0.004 0.14" scale="0.73 0.381 0.866" rotation="0 -45.664736271926614 0"></a-box><a-box material="color:#4cca10" position="0.403 0.227 -0.787" scale="0.897 0.381 0.517" rotation="0 31.168904055116787 0"></a-box><a-box material="color:#4cca10" position="-0.319 0.227 -0.881" scale="0.897 0.381 0.517" rotation="0 131.89488443911551 0"></a-box><a-box material="color:#4cca10" position="-0.345 0.841 0.233" scale="0.712 0.329 0.86"></a-box>
<a-box id="node3" material="color:#a44523" position="-0.181 -0.062 -0.317" scale="0.596 1.472 0.455"></a-box>
</a-entity>
<a-entity id="xmas_parts4" position="-0.031 4.738 -0.294" rotation="0 90 0" scale="0.808 0.808 0.808">
<a-box material="color:#4cca10" position="-0.098 1.374 -0.278" scale="0.613 0.631 0.432"></a-box><a-box material="color:#4cca10" position="0.223 1.023 -0.532" scale="0.613 0.631 0.432"></a-box><a-box material="color:#4cca10" position="0.319 0.844 0.168" scale="0.656 0.43 0.514" rotation="0 -29.621918008263563 0"></a-box><a-box material="color:#4cca10" position="-0.224 0.932 -0.029" scale="0.761 0.556 0.609" rotation="0 -21.772396214971284 0"></a-box><a-box material="color:#4cca10" position="-0.462 0.932 -0.665" scale="0.616 0.456 0.609" rotation="0 -124.15995420484938 0"></a-box><a-box material="color:#4cca10" position="-0.68 0.527 -0.555" scale="0.897 0.556 0.665"></a-box><a-box material="color:#4cca10" position="-0.456 0.209 0.013" scale="0.897 0.43 0.665"></a-box><a-box material="color:#4cca10" position="0.382 0.722 -0.373" scale="1.063 0.411 0.719"></a-box><a-box material="color:#4cca10" position="0.775 0.376 -0.34" scale="0.897 0.381 0.517"></a-box><a-box material="color:#4cca10" position="0.413 -0.004 0.14" scale="0.73 0.381 0.866" rotation="0 -45.664736271926614 0"></a-box><a-box material="color:#4cca10" position="0.403 0.227 -0.787" scale="0.897 0.381 0.517" rotation="0 31.168904055116787 0"></a-box><a-box material="color:#4cca10" position="-0.319 0.227 -0.881" scale="0.897 0.381 0.517" rotation="0 131.89488443911551 0"></a-box><a-box material="color:#4cca10" position="-0.345 0.841 0.233" scale="0.712 0.329 0.86"></a-box>
<a-box id="node4" material="color:#a44523" position="-0.181 -0.062 -0.317" scale="0.596 1.472 0.455"></a-box>
</a-entity>
</a-entity>
<!-- tree light top -->
<a-entity id="tree_light_top">
<a-entity position="-0.234 7.48 -0.175" scale="0.378 0.378 0.378" geometry="primitive:octahedron" material="emissive:#c90;color:#fff"></a-entity>
</a-entity>
<!-- tree blinks -->
<a-entity id="tree_blinks">
<a-entity id="tree_blink" position="-1.123 3.604 0.827" light="color:#F00;type:point">
<a-animation attribute="light.intensity" from="0.5" to="1.5" dur="2000" delay="0" direction="alternate" repeat="indefinite"></a-animation>
</a-entity>
<a-entity id="tree_blink-2" position="-0.263 5.522 1" light="color:#00f;intensity:3;groundColor:#fff;type:point">
<a-animation attribute="light.intensity" from="0.5" to="1.5" dur="2000" delay="200" direction="alternate" repeat="indefinite"></a-animation>
</a-entity>
<a-entity id="tree_blink-3" position="0.846 2.515 0.867" light="intensity:2.083;color:#ff0;groundColor:#fff;type:point">
<a-animation attribute="light.intensity" from="0.5" to="1.5" dur="2000" delay="400" direction="alternate" repeat="indefinite"></a-animation>
</a-entity>
<a-entity id="tree_blink-4" position="-0.111 3.017 -2.264" light="intensity:2;color:#ff0;groundColor:#fff;type:point">
<a-animation attribute="light.intensity" from="0.5" to="1.5" dur="2000" delay="800" direction="alternate" repeat="indefinite"></a-animation>
</a-entity>
</a-entity>
<!-- tree_ornaments -->
<a-entity id="tree_ornaments">
<a-entity id="tree_ornament" position="-0.188 5.978 0.589" scale="0.1 0.1 0.1" geometry="primitive:sphere" material="color:#0ff"></a-entity>
<a-entity id="tree_ornament-2" position="-1.046 4.315 0.717" scale="0.1 0.1 0.1" geometry="primitive:sphere" material="color:#ff0"></a-entity>
<a-entity id="tree_ornament-3" position="0.248 4.287 0.36" scale="0.1 0.1 0.1" geometry="primitive:sphere" material="color:#0f0"></a-entity>
<a-entity id="tree_ornament-4" position="0.653 2.871 0.431" scale="0.1 0.1 0.1" geometry="primitive:sphere" material="color:#0ff"></a-entity>
<a-entity id="tree_ornament-5" position="-0.883 2.612 1.03" scale="0.1 0.1 0.1" geometry="primitive:sphere" material="color:#f00"></a-entity><a-entity id="tree_ornament-6" position="0.783 3.137 -1.083" scale="0.1 0.1 0.1" geometry="primitive:sphere" material="color:#0ff"></a-entity><a-entity id="tree_ornament-7" position="0.18 4.207 -1.262" scale="0.1 0.1 0.1" geometry="primitive:sphere" material="color:#0f0"></a-entity><a-entity id="tree_ornament-8" position="-0.288 5.45 -0.988" scale="0.1 0.1 0.1" geometry="primitive:sphere" material="color:#f00"></a-entity><a-entity id="tree_ornament-9" position="-0.248 6.548 -0.922" scale="0.1 0.1 0.1" geometry="primitive:sphere" material="color:#ff0"></a-entity><a-entity id="tree_ornament-10" position="-1.07 2.598 -0.81" scale="0.1 0.1 0.1" geometry="primitive:sphere" material="color:#ff0"></a-entity><a-entity id="tree_ornament-11" position="-0.772 2.299 0.13" scale="0.1 0.1 0.1" geometry="primitive:sphere" material="color:#f0f"></a-entity><a-entity id="tree_ornament-12" position="-1.451 5.014 -0.048" scale="0.1 0.1 0.1" geometry="primitive:sphere" material="color:#90f"></a-entity><a-entity id="tree_ornament-13" position="-0.408 5.014 0.335" scale="0.1 0.1 0.1" geometry="primitive:sphere" material="color:#fff"></a-entity><a-entity id="tree_ornament-14" position="0.451 5.298 -0.041" scale="0.1 0.1 0.1" geometry="primitive:sphere" material="color:#0f9"></a-entity><a-entity id="tree_ornament-15" position="0.451 4.006 -0.041" scale="0.1 0.1 0.1" geometry="primitive:sphere" material="color:#ff0"></a-entity><a-entity id="tree_ornament-16" position="0.337 5.199 -0.805" scale="0.1 0.1 0.1" geometry="primitive:sphere" material="color:#f0f"></a-entity><a-entity id="tree_ornament-17" position="-0.317 6.471 0.373" scale="0.1 0.1 0.1" geometry="primitive:sphere" material="color:#fff"></a-entity>
</a-entity>
</a-entity>
<!-- // end of tree_christmas -->
<a-entity id="snow"
geometry="primitive: sphere; radius: 0.4;"
material="shader: flat; color: #fff;"
position="0 -10 0"
></a-entity>
<a-entity id="building"
geometry="primitive: box; width: 4; height: 8; depth: 4;"
material="shader: flat"
position="0 -10 0"
>
</a-entity>
<a-entity id="camera_container"
position="0 8 20" rotation="10 0 0"
data-lookat="0 0 0"
>
<a-camera id="camera_body"
far="6000"
look-controls-enabled="true"
wasd-controls-enabled="false"
></a-camera>
</a-entity>
</a-entity>
</a-scene>
1-3.3Dオブジェクトを操作するスクリプトを追加
カメラがツリーの周りをまわったり、ツリーへの照明が変化したり、雪が降ったりは、スクリプトで行います。
<script>
const settings = {
building: 60,
snow: 30
};
document.addEventListener('DOMContentLoaded', e => {
setTimeout(app, 100);
});
const app = () => {
const viewport = document.getElementById('viewport');
<!-- ーー中略ーー -->
destroy(delay){
//super.destroy();
this.status = 'will_destroy';
this.acceleration.multiply(new THREE.Vector3(0.8, 0.25, 0.8));
setTimeout(() => {
this.setup();
}, delay);
}
}
</script>
2.アカウント情報を3Dオブジェクトにする
作成したindex.htmlは、githubのindex-r2.html
です。
ログインしたアカウントのアカウント情報を取得し3Dオブジェクトを作成します。これは、どちらもスクリプトで行いました。アカウント名は、ログインが成功した後に取得できるため、オブジェクト作成時はアカウント情報がわかりません。そのため、オブジェクト作成時は、アカウント名ではなくdummy
という仮の文字列を設定します。
オブジェクトの上下移動処理に、アカウント情報が設定されたタグ(<div id="usernameTag"
・・・)からアカウント名を取得し3Dオブジェクトを更新します。
// ユーザー名を設定する
<div id="usernameTag" class="user-name">tteesstt--</div>
<script>
// 3Dオブジェクト作成
var scene = document.querySelector('a-scene');
var cylinder = document.createElement('a-text');
cylinder.setAttribute('color', '#FF9500');
cylinder.setAttribute('value', "dummy");
cylinder.setAttribute('position', { x: 50, y: 20, z: 30 });
cylinder.setAttribute('width', '50');
scene.appendChild(cylinder);
// オブジェクトを上下に移動繰り返す
var t = 0;
function render() {
t += 0.01;
requestAnimationFrame(render);
cylinder.setAttribute('position', '3 '+(Math.sin(t*2)+10)+' 0');
var nameStr = "";
nameStr += document.getElementById("usernameTag").innerText;
nameStr += "\n Merry Christmas";
cylinder.setAttribute('value', nameStr);
}
render();
</script>
課題
クリスマスツリーの描画処理はサイトを開いたタイミングで開始されます。さらに、ログイン処理が完了した後も再ロードされるので同じ処理を2回行っています。後半の1回だけに行うようにしたいところです。