Open10
【Webフレームワーク / 学習メモ】A-Frame
A-Frameとは
- WebXRに対応した、オープンソースのWebフレームワーク
- HTMLで3Dシーンの作成ができる
- A-Frame要素も、DOM操作が可能
- Unityでも採用されている、ECS(Entity Component System)が導入されている
- three.jsに基づくフレームワークのため、three.js API への完全なアクセスが可能
公式サイト
A-Frame導入方法
- HTMLファイルのヘッダー要素に、CDNでA-Frameの参照を追加することで導入可能
index.html
<head>
<script src="https://aframe.io/releases/1.4.0/aframe.min.js"></script>
</head>
A-Frameのシーン定義とPrimitive要素
index.html
<html>
<head>
<script src="https://aframe.io/releases/1.2.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>
Primitive要素 | 概要 |
---|---|
<a-scene> | canvasにレンダリングするシーン(3D空間)。 sceneタグの中に追加した内容がシーンに反映される |
<a-box> | 立方体 |
<a-sphere> | 球体 |
<a-cylinder> | 円柱 |
<a-plane> | 平面 |
<a-sky> | 背景 |
ECS(Entity-Component-System)
A-Frameは、ECSのアーキテクチャを備えている
ECSの要素
要素 | 概要 |
---|---|
Entities (エンティティ) |
・コンポーネントをアタッチできる、コンテナオブジェクト ・Unityで言うと「空のGameObject」に相当するもの ・タグ要素だと「<a-entity>」が相当する |
Components (コンポーネント) |
・再利用可能な部品 ・エンティティにアタッチすることで外観・動作・機能を提供できる ・Unityで言うと「AddComponent」して機能を与えるイメージ ・「AFRAME.registerComponent」でコンポーネントの定義が可能 |
Systems (システム) |
・コンポーネントのクラスに対してグローバルなスコープ、管理、およびサービスを提供するもの ・タグ要素だと「<a-scene>」が相当する |
ECS:コンポーネントの基本構成
index.html
AFRAME.registerComponent('foo', {
schema: {
bar: {type: 'number'},
hoge: {type: 'string'}
},
init: function () {
},
update: function () {
},
remove: function () {
},
tick: function (time, timeDelta) {
}
});
項目 | 概要 |
---|---|
registerComponentの第一引数 | コンポーネントの名称 |
registerComponentの第二引数 | コンポーネントの定義 |
schema | ・コンポーネントのプロパティを定義する部分 |
init | ・コンポーネントをエンティティに追加した際に、1回だけ呼ばれる |
update | ・コンポーネントのプロパティが更新された際に呼ばれる |
remove | ・コンポーネントが、エンティティから外された際に呼ばれる |
tick | ・毎フレーム呼ばれる |
参考URL
ECS:JavaScriptからのDOM操作
A-Frame要素も、HTML要素と同様にDOM操作が可能
要素の作成と追加(<a-entity>の場合)
const entityEL = document.createElement('a-entity');
// 例:<a-scene>要素の子要素に、<a-entity>を追加するサンプル
const sceneEl = document.querySelector("a-scene");
const entityEL = document.createElement('a-entity');
sceneEl.appendChild(entityEL);
要素の削除(<a-entity>の場合)
// 構文:削除する要素の親要素.removeChild(削除する子要素);
// 例:<a-scene>要素から、<a-entity>を削除するサンプル
const sceneEl = document.querySelector("a-scene");
const entityEl = document.querySelector("a-entity");
sceneEl.removeChild(entityEL);
querySelectorによる、要素の取得
// シーンとボックス要素を取得
const sceneEl = document.querySelector('a-scene');
const boxEl = document.querySelector('a-box');
querySelectorAllによる、要素のグループの取得
// シーン要素から、ボックス要素のグループを取得する
var sceneEl = document.querySelector('a-scene');
console.log(sceneEl.querySelectorAll('a-box'));
// ログ出力例(box要素が2つ存在した場合)
// 出力: NodeList(2) [a-box, a-box]
コンポーネントの追加・更新
追加も更新も「setAttribute」を使う
entityEl.setAttribute('コンポーネント名', 設定するプロパティ値);
// 例:ジオメトリの種類、高さ、幅 を指定する
entityEl.setAttribute('geometry', {
primitive: 'box',
height: 3,
width: 1
});
コンポーネントの削除
entityEl.removeAttribute('コンポーネント名');
参考URL
ECS:コンポーネント内でのプロパティ参照
プロパティ | 概要 |
---|---|
this.data | コンポーネントのプロパティ |
this.el | HTML 要素としてのエンティティへの参照 |
this.el.sceneEl | HTML 要素としてのシーンへの参照 |
this.id | コンポーネントの個々のインスタンスの ID(コンポーネントが複数のインスタンスを持つことができる場合) |
「this.data」の参照例
「this.data.〜」という形でプロパティ参照する
AFRAME.registerComponent('foo', {
schema: {
my_val_1: {type: 'number', default: 12345},
my_val_2: {type: 'string', default: 'あいうえお'},
},
init: function () {
console.log(this.data.my_val_1);
console.log(this.data.my_val_2);
}
});
参考URL
ECS:コンポーネントの参照
AFRAME.registerComponent('foo', {
init: function () {
}
});
var fooComponent = document.querySelector('[foo]').components.foo;
console.log(fooComponent);
参考URL
ECS:コンポーネントのメンバー変数、メソッドへのアクセス
AFRAME.registerComponent('foo', {
schema: {
my_data: {type: 'string', default: 'あいうえお'},
},
// LifeCycle Methods
init: function() {
this.bar = 12345;
},
// Original Methods
message: function() {
console.log(`message : ${this.data.my_data}`);
},
});
var fooComponent = document.querySelector('[foo]').components.foo;
console.log(fooComponent.bar);
console.log(fooComponent.message());
参考URL