Entity
A-Frame represents an entity via the <a-entity> element. As defined in the
entity-component-system pattern, entities are placeholder objects to
which we plug in components to provide them appearance, behavior, and
functionality.
A-Frameは<a-entity>要素でエンティティを表現します。エンティティコンポーネントシステムパターンで定義されているように、エンティティとは、外観、動作、機能を提供するためにコンポーネントを差し込むプレースホルダーオブジェクトのことです。
A-Frameでは、エンティティは、位置、回転、[スケール][sclae]の各コンポーネントと本質的に結びついています。
# 例
下のような実体だけだけでは、外観も動作も機能もありません。何もしないのです。
<a-entity>
これにコンポーネントを取り付けて、何かをレンダリングさせたり、何かをさせたりすることができるのです。形状や外観を与えるために、ジオメトリとマテリアルのコンポーネントをアタッチすることができます。
<a-entity geometry="primitive: box" material="color: red">
発光させるためには、lightコンポーネントをつけます。
<a-entity geometry="primitive: box" material="color: red"
light="type: point; intensity: 2.0">
# Retrieving an Entity
DOM APIを使えば簡単にエンティティを取り出すことができます。
<a-entity id="mario"></a-entity>
var el = document.querySelector('#mario');
エンティティを取得すると、そのプロパティと以下のメソッドにアクセスできるようになります。
# プロパティ
# components
<a-entity>.componentsは、エンティティに付属するコンポーネントのオブジェクトです。これにより、各コンポーネントのデータ、状態、メソッドを含むエンティティのコンポーネントにアクセスすることができます。
例えば、あるエンティティのthree.jsカメラオブジェクトやマテリアルオブジェクトを取得したい場合、そのコンポーネントにアクセスすることができます。
var camera = document.querySelector('a-entity[camera]').components.camera.camera;
var material = document.querySelector('a-entity[material]').components.material.material;
あるいは、コンポーネントがAPIを公開している場合は、そのメソッドを呼び出すこともできる。
document.querySelector('a-entity[sound]').components.sound.pause();
# hasLoaded
エンティティがすべてのコンポーネントをアタッチし、初期化したかどうかを確認します。 もっとも、エンティティが準備できた後にコードを実行するようにするには、コンポーネントの中にコードを配置するのが一番です。
# isPlaying
エンティティがアクティブであるかどうか、再生中であるかどうか。もし実体を一時停止すれば,isPlayingはfalseになる.
# object3D
<a-entity>.object3D は、エンティティの three.js Object3D (opens new window) 表現への参照を行います。具体的には、object3DはTHREE.Groupオブジェクトとなり、カメラ、メッシュ、ライト、サウンドなど、さまざまなタイプのTHREE.Object3Dが含まれる可能性があります。
// Gaining access to the internal three.js scene graph.
var groupObject3D = document.querySelector('a-entity').object3D;
console.log(groupObject3D.parent);
console.log(groupObject3D.children);
Object3DMapを通じて、様々なタイプのObject3Dにアクセスすることができます。
# object3DMap
An entity's object3DMap is an object that gives access to the different types
of THREE.Object3Ds (e.g., camera, meshes, lights, sounds) that components
have set.
エンティティのobject3DMapは、コンポーネントが設定したさまざまな種類のTHREE.Object3D(カメラ、メッシュ、ライト、サウンドなど)にアクセスするためのオブジェクトです。
ジオメトリと[ライト][light}のコンポーネントがアタッチされているエンティティの場合、object3DMapは次のようになります。
{
light: <THREE.Light Object>,
mesh: <THREE.Mesh Object>
}
setObject3D、removeObject3Dを使用することで、エンティティのTHREE.Object3Dセットを管理することができます。
# sceneEl
エンティティがそのシーンエレメントへの参照を持つことができます。
var sceneEl = document.querySelector('a-scene');
var entity = sceneEl.querySelector('a-entity');
console.log(entity.sceneEl === sceneEl); // >> true.
# メソッド
# addState (stateName)
addState will push a state onto the entity. This will emit the stateadded
event, and we can check the state can for existence using .is:
エンティティに状態(ステート)をプッシュします。これによりstateaddedイベントが発生し、.isを使ってstate canが存在するかどうかを確認することができます。
entity.addEventListener('stateadded', function (evt) {
if (evt.detail === 'selected') {
console.log('Entity now selected!');
}
});
entity.addState('selected');
entity.is('selected'); // >> true
# destroy ()
すべてのコンポーネントとそのデータをクリアするなど、エンティティに関連するメモリを一掃します。
# emit (name, detail, bubbles)
emit` は、エンティティに対してカスタム DOM イベントを発行します。例えば、以下のようなアニメーションをトリガーするイベントを発行することができます。
// <a-entity animation="property: rotation; to: 0 360 0; startEvents: rotate">
entity.emit('rotate');
また、第2引数としてイベントの詳細やデータを渡すことができます。
entity.emit('collide', { target: collidingEntity });
このイベントはデフォルトでバブル化されますが、バブル化しないようにするにはbubbleにfalseを渡します。
entity.emit('sink', null, false);
# flushToDOM (recursive)
flushToDOM will manually serialize an entity's components' data and update the DOM.
Read more about component-to-DOM serialization.
# getAttribute (componentName)
getAttribute は、パースされたコンポーネントデータ (ミックスインやデフォルトを含む) を取得します。
// <a-entity geometry="primitive: box; width: 3">
entity.getAttribute('geometry');
// >> {primitive: "box", depth: 2, height: 2, width: 3, ...}
entity.getAttribute('geometry').primitive;
// >> "box"
entity.getAttribute('geometry').height;
// >> 2
entity.getAttribute('position');
// >> {x: 0, y: 0, z: 0}
もし componentName が登録されたコンポーネントの名前でない場合、 getAttribute がそのように動作します。
// <a-entity data-position="0 1 1">
entity.getAttribute('data-position');
// >> "0 1 1"
# getDOMAttribute (componentName)
getDOMAttribute retrieves only parsed component data that is explicitly
defined in the DOM or via setAttribute. If componentName is the name of a
registered component, getDOMAttribute will return only the component data
defined in the HTML as a parsed object. getDOMAttribute for components is
the partial form of getAttribute since the returned component data does not
include applied mixins or default values:
getDOMAttribute は、解析されたコンポーネントのうち、DOM で定義されているか、 setAttribute によって定義されている明示的に指定されたデータのみを取得します。
もし、 componentName が登録されたコンポーネントをである場合、getDOMAttributeはHTMLの中でオブジェクトとしてパースされたコンポーネントデータのみを返します。
コンポーネント用の getDOMAttribute はgetattributeの部分的なフォームです。
なので、返されたコンポーネントデータには適用されたミキシンやデフォルト値は含まれません。
上記のgetAttributeの例での出力結果を比べてみましょう。
// <a-entity geometry="primitive: box; width: 3">
entity.getDOMAttribute('geometry');
// >> { primitive: "box", width: 3 }
entity.getDOMAttribute('geometry').primitive;
// >> "box"
entity.getDOMAttribute('geometry').height;
// >> undefined
entity.getDOMAttribute('position');
// >> undefined
# getObject3D (type)
getObject3D は object3DMap 上のtype で参照される子オブジェクト THREE.Object3D を検索します。
AFRAME.registerComponent('example-mesh', {
init: function () {
var el = this.el;
el.setObject3D('mesh', new THREE.Mesh());
el.getObject3D('mesh'); // Returns THREE.Mesh that was just created.
}
});
# pause ()
pause() は、アニメーションやコンポーネントで定義された動的な動作を停止させます。エンティティを一時停止すると、そのアニメーションが停止し、各コンポーネントで Component.pause() が呼び出されます。コンポーネントは、一時停止時に何が起こるかを実装しますが、それは多くの場合、イベントリスナーを削除することが多いです。エンティティを一時停止すると、エンティティはその子エンティティに対してpause()を呼び出します。
// <a-entity id="spinning-jumping-ball">
entity.pause();
例えば、この停止中のlook-controls コンポーネントは、入力をリッスンするイベントハンドラを削除します。
# play ()
play() は、アニメーションやコンポーネントで定義された動的な動作を開始させます。これは、DOM がエンティティをアタッチしたときに自動的に呼び出されます。エンティティが play() を実行すると、そのエンティティは子エンティティに対して play() を呼び出します。
entity.pause();
entity.play();
例えば、playのsoundコンポーネントは、音の再生を開始します。
# setAttribute (componentName, value, [propertyValue | clobber])
componentName が登録されたコンポーネント名でない場合、またはコンポーネントが単独のプロパティコンポーネントの場合、setAttribute は通常と同様に動作します。
entity.setAttribute('visible', false);
ただし、componentNameが登録されたコンポーネントの名前である場合、その値に対して特別なパージングを処理することがあります。例えば、positionコンポーネントはシングルプロパティコンポーネントですが、そのプロパティタイプパーサはオブジェクトを取得することを許可します。
entity.setAttribute('position', { x: 1, y: 2, z: 3 });
# 復数のプロパティを持つコンポーネントデータを更新する
復数のプロパティコンポーネントを持つコンポーネントデータを更新するには、登録されているコンポーネントの名前をcomponentNameとして渡し、プロパティのオブジェクトをvalueとして渡します。文字列でも構いませんが(例:type: spot; distance: 30)、オブジェクトの方がA-Frameのパース作業が軽減されます。
// Only the properties passed in the object will be overwritten.
entity.setAttribute('light', {
type: 'spot',
distance: 30,
intensity: 2.0
});
また、復数のプロパティコンポーネントの個々のプロパティを更新するには、登録されたコンポーネントの名前をcomponentName、プロパティ名を第2引数、設定するプロパティ値を第3引数として渡します。
// All previous properties for the material component (besides the color) will be unaffected.
entity.setAttribute('material', 'color', 'crimson');
配列のプロパティタイプは一意的に動作することに注意してください。
- 配列は変更可能です。配列は参照によって割り当てられるので、配列の変更はコンポーネントによって可視化されます。
- 配列のプロパティが更新されても、コンポーネントの
updateメソッドは起動しませんし、イベントも発生しません。
# 復数のプロパティを持つコンポーネントデータを配置する
.setAttributeの第3引数にtrueが渡されると、指定されていないプロパティはリセットされ、clobberedされます。
// All previous properties for the light component will be removed and overwritten.
entity.setAttribute('light', {
type: 'spot',
distance: 30,
intensity: 2.0
}, true);
# setObject3D (type, obj)
setObject3Dは、渡されたTHREE.Object3Dであるobjをエンティティのobject3DMapの下にtypeとして登録します。
A-Frameはobjをエンティティのルートであるobject3Dの子要素として追加します。setObject3Dが呼ばれると、エンティティはtype イベントの詳細でobject3dsetイベントを発行します。
AFRAME.registerComponent('example-orthogonal-camera', {
update: function () {
this.el.setObject3D('camera', new THREE.OrthogonalCamera());
}
});
# removeAttribute (componentName, propertyName)
componentName が登録されたコンポーネントの名前である場合、DOM から属性を削除すると同時に、removeAttribute はコンポーネントを実体から切り離し、コンポーネントの remove ライフサイクルメソッドを呼び出します。
entity.removeAttribute('geometry'); // Detach the geometry component.
entity.removeAttribute('sound'); // Detach the sound component.
propertyName が指定された場合、removeAttribute は propertyName で指定されたそのプロパティの値をそのプロパティのデフォルト値にリセットする。
entity.setAttribute('material', 'color', 'blue'); // The color is blue.
entity.removeAttribute('material', 'color'); // Reset the color to the default value, white.
# removeObject3D (type)
removeObject3D は、type で指定されたオブジェクトをエンティティの THREE.Group から、ひいてはシーンから削除します。
エンティティのobject3DMapを更新し、typeキーの値をnullに設定します。通常、コンポーネントから呼び出され、removeハンドラ内で使用されます。
AFRAME.registerComponent('example-light', {
update: function () {
this.el.setObject3D('light', new THREE.Light());
// Light is now part of the scene.
// object3DMap.light is now a THREE.Light() object.
},
remove: function () {
this.el.removeObject3D('light');
// Light is now removed from the scene.
// object3DMap.light is now null.
}
});
# removeState (stateName)
removeStateは、エンティティからステートをポップします。これはstateremovedイベントを発生させ、.isを使用して状態が削除されたことを確認することができます。
entity.addEventListener('stateremoved', function (evt) {
if (evt.detail.state === 'selected') {
console.log('Entity no longer selected.');
}
});
entity.addState('selected');
entity.is('selected'); // >> true
entity.removeState('selected');
entity.is('selected'); // >> false
# Events
| イベント名 | 概要 |
|---|---|
| child-attached | 子エンティティがエンティティにアタッチされました。 |
| child-detached | 子エンティティがエンティティから切り離された。 |
| componentchanged | エンティティのコンポーネントの1つが変更された。このイベントはスロットルされています。位置や回転の変更の読み取りには使用せず、ティックハンドラを使用してください。 |
| componentinitialized | エンティティのコンポーネントの 1 つが初期化されました。 |
| componentremoved | エンティティのコンポーネントの 1 つが削除された。 |
| loaded | エンティティのコンポーネントがアタッチされ、初期化されました。 |
| object3dset | THREE.Object3D が setObject3D(name) でエンティティに設定された。イベント詳細には、object3DMapに設定するために使用したnameが含まれます。 |
| pause | エンティティが非アクティブになり、動的動作が一時停止しました。 |
| play | エンティティは現在アクティブで、動的な動作の観点から再生されています。 |
| stateadded | エンティティは新しい状態を受け取った。 |
| stateremoved | エンティティがある状態を持たなくなった。 |
| schemachanged | コンポーネントのスキーマが変更された。 |
# Event Detail
Below is what the event detail contains for each event:
| Event Name | Property | Description |
|---|---|---|
| child-attached | el | 付属の子要素への参照。 |
| componentchanged | name | データが変更されたコンポーネントの名前。 |
| id | id データが変更されたコンポーネントのID。 | |
| componentinitialized | name | 初期化されたコンポーネントの名前。 |
| id | データが変更されたコンポーネントのID。 | |
| data | コンポーネントのデータです。 | |
| componentremoved | name | 削除されたコンポーネントの名前です。 |
| id | 削除されたコンポーネントのIDです。 | |
| stateadded | N/A | 付加された状態(文字列)。 |
| stateremoved | N/A | 取り外された状態(文字列)。 |
| schemachanged | component | Nスキーマが変更されたコンポーネントの名前。 |
# コンポーネントの変化をリッスンする
componentchangedイベントを使用して、エンティティへの変更をリッスンすることができます。
entity.addEventListener('componentchanged', function (evt) {
if (evt.detail.name === 'position') {
console.log('Entity has moved to', evt.target.getAttribute('position'), '!');
}
});
# 子要素のアタッチメントとアタッチメント解除をリスニングする
child-attachedとchild-detachedイベントを使うと、シーンがエンティティをアタッチまたはデタッチするタイミングをリッスンすることができます。
entity.addEventListener('child-attached', function (evt) {
if (evt.detail.el.tagName.toLowerCase() === 'a-box') {
console.log('a box element has been attached');
};
});