当前位置: 首页 > 文档资料 > A-Frame 中文文档 >

实体(Entity)

优质
小牛编辑
139浏览
2023-12-01

A-Frame使用<a-entity>元素来表示一个实体。如同在 实体-组件-系统模式中定义的,实体是占位符对象以便我们插入组件来提供其外观、行为和 功能。

在A-Frame中,位置(position)旋转(rotation)尺寸(scale)是实体的固有组件。

例子

考虑下面的实体。就其本身而言,它没有外表、行为或功能.它什么也不做:

<a-entity>

我们可以将给它附加组件,使它呈现某事或做某事。为了使它具有形状和外观,我们可以加上几何模型(geometry)材料(material)组件:

<a-entity geometry="primitive: box" material="color: red">

或者为了使它发光,我们可以进一步附加光照(light)组件:

<a-entity geometry="primitive: box" material="color: red"          light="type: point; intensity: 2.0">

获得一个实体

我们可以使用简单的DOM应用程序接口来得到一个实体。

<a-entity></a-entity>
var el = document.querySelector('#mario');

一旦我们得到了一个实体,我们就可以访问它的属性和方法了。

属性(Properties)

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();

isPlaying

该属性表示这个实体是否处于活动状态中。如果我们暂停该实体,那么isPlaying 将变为 false

object3D

<a-entity>.object3D是对实体的three.js Object3D对象的引用。准确的说,object3D是一个THREE.Group对象,其中包含了各种THREE.Object3D对象,如相机(cameras), 网孔(meshes), 光照(lights)或者声音:

// Gaining access to the internal three.js scene graph.var groupObject3D = document.querySelector('a-entity').object3D;console.log(groupObject3D.parent);console.log(groupObject3D.children);

We can access the different types of Object3Ds through object3DMap.

object3DMap

一个实体的object3DMap是一个对象,它允许访问组件所设置的不同类型的THREE.Object3D,如相机(cameras), 网孔(meshes), 光照(lights)或者声音。

对于一个附有geometrylight组件的实体,object3DMap可能看起来如下:

{  light: <THREE.Light Object>,  mesh: <THREE.Mesh Object>}

我们可以使用getOrCreateObject3DsetObject3D,以及removeObject3D来管理实体的THREE.Object3D集合。

sceneEl

实体包含一个对其所在场景元素的引用。

var sceneEl = document.querySelector('a-scene');var entity = sceneEl.querySelector('a-entity');console.log(entity.sceneEl === sceneEl);  // >> true.

方法(Methods)

addState (stateName)

addState给实体添加状态,该方法将发出stateadded事件,而且我们可以通过.is来检查状态是否存在:

entity.addEventListener('stateadded', function (evt) {  if (evt.detail.state === 'selected') {    console.log('Entity now selected!');  }});entity.addState('selected');entity.is('selected');  // >> true

emit (name, detail, bubbles)

emit在实体上发出自定义DOM事件。例如,我们可以触发一个动画:

// <a-entity>//   <a-animation attribute="rotation" begin="rotate" to="0 360 0"></a-animation>// </a-entity>entity.emit('rotate');

我们也可以使用第二个参数来传递事件细节或数据:

entity.emit('collide', { target: collidingEntity });

默认情况下该事件将冒泡(向父级对象上溯)。我们可以禁止事件冒泡:

entity.emit('sink', null, false);

flushToDOM (recursive)

flushToDOM将手动序列化实体组件的数据并更新DOM。阅读更多:component-to-DOM序列化

getAttribute (componentName)

getAttribute获取解析组件数据(包含mixins和defaults)。

// <a-entity geometry="primitive: box; width: 3">entity.getAttribute('geometry');// >> {primitive: "box", depth: 2, height: 2, translate: "0 0 0", width: 3, ...}entity.getAttribute('geometry').primitive;// >> "box"entity.getAttribute('geometry').height;// >> 2entity.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仅获取显式定义在DOM中或通过setAttribute方法设置的解析组件数据。如果componentName是一个已注册组件的名称,getDOMAttribute将以一个解析对象返回定义在HTML中的组件数据。对于组件,getDOMAttribute只是getAttribute的部分形式,因为返回的组件数据不包括被应用的混合(mixins)或默认值(defauls):

比较上述getObject3D (type)

getObject3Dobject3DMap上按type引用来查找一个子THREE.Object3D

AFRAME.registerComponent('example-mesh', {  init: function () {    var el = this.el;    el.getOrCreateObject3D('mesh', THREE.Mesh);    el.getObject3D('mesh');  // Returns THREE.Mesh that was just created.  }});

getOrCreateObject3D (type, Constructor)

当该实体在type下没有注册一个THREE.Object3D时,getOrCreateObject3D方法将使用传入的Constructor来注册一个实例化的THREE.Object3D。如果实体在type下已有一个注册的THREE.Object3DgetOrCreateObject3D方法效果和getObject3D一样:

AFRAME.registerComponent('example-geometry', {  update: function () {    var mesh = this.el.getOrCreateObject3D('mesh', THREE.Mesh);    mesh.geometry = new THREE.Geometry();  }});

pause ()

pause()将停止任何动画和组件所定义的动态行为。当我们暂停某个实体时,它将停止其动画并在其每个组件上调用Component.pause()。组件决定执行暂停时要发生的事情,通常是删除事件侦听器。当我们暂停一个实体时,它将在其所有子实体上调用pause()

// <a-entity>entity.pause();

For example, the look-controls component on pause will remove event handlers that listen for input.

play ()

play()将启动任何动画和组件所定义的动态行为。DOM附加实体时会自动调用它。当一个实体调用play(),该实体将在其所有子实体上调用play()

entity.pause();entity.play();

例如,当sound组件调用play方法时,将播放声音。

setAttribute (attr, value, componentAttrValue)

如果attr不是一个注册组件的名称或者这个组件是一个单属性组件,setAttribute会按正常情况工作:

entity.setAttribute('visible', false);

但是,如果attr是一个注册组件的名称,它可能会对该值进行特殊解析处理。比如position组件是一个单属性组件,但是它的属性类型解析器允许它接受一个对象(object):

entity.setAttribute('position', { x: 1, y: 2, z: 3 });

设置多属性组件数据

若要设置或替换多属性组件的组件数据,我们可以通过attr参数来传递一个注册组件的名称,并通过value传递一个属性对象:

// All previous properties for the light component will be removed and overwritten.entity.setAttribute('light', {  type: 'spot',  distance: 30,  intensity: 2.0});

更新多属性组件数据

若要更新多属性组件的单个属性,可以通过attr传递已注册组件的名称,通过第2个参数传递一个属性名称,第3个参数传递要设置的属性值:

// 材料组件的所有之前的属性(除了颜色)都不会受到影响。entity.setAttribute('material', 'color', 'crimson');

setObject3D (type, obj)

setObject3D将注册传递的obj对象,这是一个THREE.Object3D,作为该实体的object3DMap下面的一个type。A-Frame添加obj为实体根object3D对象的子对象。

AFRAME.registerComponent('example-orthogonal-camera', {  update: function () {    this.el.setObject3D('camera', new THREE.OrthogonalCamera());  }});

removeAttribute (attr, propertyName)

如果attr是一个注册组件的名称,除了从DOM中删除属性之外,removeAttribute将从实体中去除该组件,并触发该组件的remove生命周期方法。

entity.removeAttribute('goemetry');  // Detach the geometry component.entity.removeAttribute('sound');  // Detach the sound component.

如果给定propertyNameremoveAttribute将重置由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。这通常是从组件的删除处理程序中调用。

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');  // >> trueentity.removeState('selected');entity.is('selected');  // >> false

事件(Events)

事件名称描述
child-attached一个子实体被附加到实体上。
child-detached一个子实体被从实体中分离出去。
componentchanged实体的一个组件被修改了。
componentinit实体的一个组件被初始化了。
componentremoved实体的一个组件被初删除了。
loaded实体已经添加并初始化了它的组件。
object3dsetTHREE.Object3D被通过setObject3D(name)方法设置在实体上。事件细节将包含用来设置在object3DMap中的name
实体现在处于非活动状态(或暂停)。
play实体现在处于活动状态(或播放)。
stateadded实体收到一个新的状态。
stateremoved实体不再具有某种状态。
schemachanged组件的模式已更改。

事件细节

下面是每个事件所包含的细节:

事件名称属性描述
child-attachedel所附加子元素的引用。
componentchangedname被修改数据的组件的名称。
id被修改数据的组件的ID。
newData组件被修改后的新数据。
oldData组件被修改前的旧数据。
componentinitializedname被初始化的组件的名称。
id被修改数据的组件的ID。
data组件数据
componentremovedname被删除的组件的名称。
id被删除的组件的ID。
stateaddedstate被附加的状态(字符串)。
stateremovedstate被分离(去除)的状态(字符串)。
schemachangedcomponent被修改模式的组件的名称。

侦听组件变更

我们可以使用componentchanged事件来侦听实体的变更:

entity.addEventListener('componentchanged', function (evt) {  if (evt.detail.name === 'position') {    console.log('Entity has moved from', evt.detail.oldData, 'to', evt.detail.newData, '!');  }});

倾听子元素的添加和去除

我们可以使用child-attachedchild-detached事件来侦听什么时候场景添加和去除了一个实体:

entity.addEventListener('child-attached', function (evt) {  if (evt.detail.el.tagName.toLowerCase() === 'a-box') {    console.log('a box element has been attached');  };});