This section provides an overview of what aframe is, and why a developer might want to use it.
It should also mention any large subjects within aframe, and link out to the related topics. Since the Documentation for aframe is new, you may need to create initial versions of those related topics.
Name | Details |
---|---|
raycaster-intersected | Emitted on the intersected entity. Entity is intersecting with a raycaster. Event detail will contain el, the raycasting entity, and intersection, an object containing detailed data about the intersection. |
raycaster-intersected-cleared | Emitted on the intersected entity. Entity is no longer intersecting with a raycaster. Event detail will contain el, the raycasting entity. |
raycaster-intersection | Emitted on the raycasting entity. Raycaster is intersecting with one or more entities. Event detail will contain els, an array with the intersected entities, and intersections, an array of objects containing detailed data about the intersections. |
raycaster-intersection-cleared | Emitted on the raycasting entity. Raycaster is no longer intersecting with an entity. Event detail will contain el, the formerly intersected entity. |
Member | Description |
---|---|
intersectedEls | Entities currently intersecting the raycaster. |
objects | three.js objects to test for intersections. Will be scene.children if not objects property is not specified. |
raycaster | three.js raycaster object. |
Method | Description |
---|---|
refreshObjects | Refreshes the list of objects based off of the objects property to test for intersection. |
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:
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 emits a custom DOM event on the entity. For example, we can emit an event to trigger an animation:
<a-entity>
<a-animation attribute="rotation" begin="rotate" to="0 360 0"></a-animation>
</a-entity>
entity.emit('rotate');
We can also pass event detail or data as the second argument:
entity.emit('collide', { target: collidingEntity });
The event will bubble by default. we can tell it not to bubble by passing false for bubble:
entity.emit('sink', null, false);
flushToDOM (recursive)
flushToDOM will manually serialize an entity’s components’ data and update the DOM.
getAttribute (componentName)
getAttribute retrieves parsed component data (including mixins and 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;
// >> 2
entity.getAttribute('position');
// >> {x: 0, y: 0, z: 0}
If componentName is not the name of a registered component, getAttribute will behave as it normally would:
// <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:
Compare the output of the above example of 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 looks up a child THREE.Object3D referenced by type on object3DMap.
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)
If the entity does not have a THREE.Object3D registered under type, getOrCreateObject3D will register an instantiated THREE.Object3D using the passed Constructor. If the entity does have an THREE.Object3D registered under type, getOrCreateObject3D will act as getObject3D:
AFRAME.registerComponent('example-geometry', {
update: function () {
var mesh = this.el.getOrCreateObject3D('mesh', THREE.Mesh);
mesh.geometry = new THREE.Geometry();
}
});
pause ()
pause() will stop any dynamic behavior as defined by animations and components. When we pause an entity, it will stop its animations and call Component.pause() on each of its components. The components decide to implement what happens on pause, which is often removing event listeners. An entity will call pause() on its child entities when we pause an entity.
// <a-entity id="spinning-jumping-ball">
entity.pause();
For example, the look-controls component on pause will remove event handlers that listen for input.
play ()
play() will start any dynamic behavior as defined by animations and components. This is automatically called when the DOM attaches an entity. When an entity play(), the entity calls play() on its child entities.
entity.pause();
entity.play();
For example, the sound component on play will begin playing the sound.
setAttribute (componentName, value, [propertyValue | clobber])
If componentName is not the name of a registered component or the component is a single-property component, setAttribute behaves as it normally would:
entity.setAttribute('visible', false);
Though if componentName is the name of a registered component, it may handle special parsing for the value. For example, the position component is a single-property component, but its property type parser allows it to take an object:
entity.setAttribute('position', { x: 1, y: 2, z: 3 });
setObject3D (type, obj)
setObject3D will register the passed obj, a THREE.Object3D, as type under the entity’s object3DMap. A-Frame adds obj as a child of the entity’s root object3D.
AFRAME.registerComponent('example-orthogonal-camera', {
update: function () {
this.el.setObject3D('camera', new THREE.OrthogonalCamera());
}
});
removeAttribute (componentName, propertyName)
If componentName is the name of a registered component, along with removing the attribute from the DOM, removeAttribute will also detach the component from the entity, invoking the component’s remove lifecycle method.
entity.removeAttribute('goemetry'); // Detach the geometry component.
entity.removeAttribute('sound'); // Detach the sound component.
If propertyName is given, removeAttribute will reset the property value of that property specified by propertyName to the property’s default value:
entity.setAttribute('material', 'color', 'blue'); // The color is blue.
entity.removeAttribute('material', 'color'); // Reset the color to the default value, white.
removeObject3D (type)
removeObject3D removes the object specified by type from the entity’s THREE.Group and thus from the scene. This will update the entity’s object3DMap, setting the value of the type key to null. This is generally called from a component, often within the remove handler:
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 will pop a state from the entity. This will emit the stateremoved event, and we can check the state its removal using .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
Event Name | Description |
---|---|
child-attached | A child entity was attached to the entity. |
child-detached | A child entity was detached from the entity. |
componentchanged | One of the entity’s components was modified. |
componentinit | One of the entity’s components was initialized. |
componentremoved | One of the entity’s components was removed. |
loaded | The entity has attached and initialized its components. |
object3dset | THREE.Object3D was set on entity using setObject3D(name). Event detail will contain name used to set on the object3DMap. |
pause | The entity is now inactive and paused in terms of dynamic behavior. |
play | The entity is now active and playing in terms of dynamic behavior. |
stateadded | The entity received a new state. |
stateremoved | The entity no longer has a certain state. |
schemachanged | The schema of a component was changed. |
Below is what the event detail contains for each event:
Event Name | Property | Description |
---|---|---|
child-attached | el | Reference to the attached child element. |
componentchanged | name | Name of component that had its data modified. |
id | ID of component that had its data modified. | |
newData | Component’s new data, after it was modified. | |
oldData | Component’s previous data, before it was modified. | |
componentinitialized | name | Name of component that was initialized. |
id | ID of component that had its data modified. | |
data | Component data. | |
componentremoved | name | Name of component that was removed. |
id | ID of component that was removed. | |
stateadded | state | The state that was attached (string). |
stateremoved | state | The state that was detached (string). |
schemachanged | component | Name of component that had it’s schema changed. |
A system, like a component, defines lifecycle handlers. It can also define methods intended to be public API.
Method | Description |
---|---|
init | Called once when the system is initialized. Used to initialize. |
pause | Called when the scene pauses. Used to stop dynamic behavior. |
play | Called when the scene starts or resumes. Used to start dynamic behavior. |
tick | If defined, will be called on every tick of the scene's render loop. |
With the schema being the anatomy, the lifecycle methods are the physiology; the schema defines the shape of the data, the lifecycle handler methods use the data to modify the entity. The handlers will usually interact with the Entity API.
Method | Description |
---|---|
init | Called once when the component is initialized. Used to set up initial state and instantiate variables. |
update | Called both when the component is initialized and whenever any of the component's properties is updated (e.g, via setAttribute). Used to modify the entity. |
remove | Called when the component is removed from the entity (e.g., via removeAttribute) or when the entity is detached from the scene. Used to undo all previous modifications to the entity. |
tick | Called on each render loop or tick of the scene. Used for continuous changes or checks. |
play | Called whenever the scene or entity plays to add any background or dynamic behavior. Also called once when the component is initialized. Used to start or resume behavior. |
pause | Called whenever the scene or entity pauses to remove any background or dynamic behavior. Also called when the component is removed from the entity or when the entity is detached from the scene. Used to pause behavior. |
updateSchema | Called whenever any of the component's properties is updated. Can be used to dynamically modify the schema. |
Within the methods, we have access to the component prototype via this
:
Property | Description |
---|---|
this.data | Parsed component properties computed from the schema default values, mixins, and the entity's attributes. |
this.el | Reference to the [entity][entity] as an HTML element. |
this.el.sceneEl | Reference to the [scene][scene] as an HTML element. |
this.id | If the component can have [multiple instances][multiple], the ID of the individual instance of the component (e.g., foo from sound__foo ). |
.init ()
.init ()
is called once at the beginning of the component's lifecycle.
An entity can call the component's init
handler:
setAttribute
.appendChild
.The init
handler is often used to:
For example, a cursor component's init
would set state variables, bind
methods, and add event listeners:
AFRAME.registerComponent('cursor', {
// ...
init: function () {
// Set up initial state and variables.
this.intersection = null;
// Bind methods.
this.onIntersection = AFRAME.utils.bind(this.onIntersection, this);
// Attach event listener.
this.el.addEventListener('raycaster-intersection', this.onIntersection);
}
// ...
});
.update (oldData)
.update (oldData)
is called whenever the component's properties change,
including at the beginning of the component's lifecycle. An entity can call a
component's update
handler:
init ()
is called, at the beginning of component's lifecycle..setAttribute
.The update
handler is often used to:
this.data
.Granular modifications to the entity can be done by [diffing][diff] the current
dataset (this.data
) with the previous dataset before the update (oldData
).
A-Frame calls .update()
both at the beginning of a component's lifecycle and every
time a component's data changes (e.g., as a result of setAttribute
). The
update handler often uses this.data
to modify the entity. The update handler
has access to the previous state of a component's data via its first argument.
We can use the previous data of a component to tell exactly which
properties changed to do granular updates.
For example, the visible component's update
sets the visibility of
the entity.
AFRAME.registerComponent('visible', {
/**
* this.el is the entity element.
* this.el.object3D is the three.js object of the entity.
* this.data is the component's property or properties.
*/
update: function (oldData) {
this.el.object3D.visible = this.data;
}
// ...
});
.remove ()
.remove ()
is called whenever the component is detached from the entity. An
entity can call a component's remove
handler:
removeAttribute
.removeChild
).The remove
handler is often used to:
For example, when the [light component][light] is removed, the light component will remove the light object that it had previously set on the entity, thus removing it from the scene.
AFRAME.registerComponent('light', {
// ...
remove: function () {
this.el.removeObject3D('light');
}
// ...
});
.tick (time, timeDelta)
.tick ()
is called on each tick or frame of the scene's render loop. The scene
will call a component's tick
handler:
The tick
handler is often used to:
The tick
handler is provided the global uptime of the scene in milliseconds
(time
) and the time difference in milliseconds since the last frame
(timeDelta
). These can be used for interpolation or to only run parts of the
tick
handler on a set interval.
For example, the tracked controls component will progress the controller's animations, update the controller's position and rotation, and check for button presses.
AFRAME.registerComponent('tracked-controls', {
// ...
tick: function (time, timeDelta) {
this.updateMeshAnimation();
this.updatePose();
this.updateButtons();
}
// ...
});
.pause ()
.pause ()
is called when the entity or scene pauses. The entity can call a
component's pause
handler:
remove
handler is called.Entity.pause ()
.Scene.pause ()
(e.g., the Inspector is opened).The pause
handler is often used to:
For example, the sound component will pause the sound and remove an event listener that would have played a sound on an event:
AFRAME.registerComponent('sound', {
// ...
pause: function () {
this.pauseSound();
this.removeEventListener();
}
// ...
});
.play ()
.play ()
is called when the entity or scene resumes. The entity can call
a component's play
handler:
update
handler is called.Entity.play ()
.Scene.play ()
.The play
handler is often use to:
For example, the sound component will play the sound and update the event listener that would play a sound on an event:
AFRAME.registerComponent('sound', {
// ...
play: function () {
if (this.data.autoplay) { this.playSound(); }
this.updateEventListener();
}
// ...
});
.updateSchema (data)
.updateSchema ()
, if defined, is called on every update in order to check if
the schema needs to be dynamically modified.
The updateSchema
handler is often used to:
For example, the geometry component checks if the primitive
property changed to determine whether to update the schema for a different
type of geometry:
AFRAME.registerComponent('geometry', {
// ...
updateSchema: (newData) {
if (newData.primitive !== this.data.primitive) {
this.extendSchema(GEOMETRIES[newData.primitive].schema);
}
}
// ...
});
.flushToDOM ()
To save on CPU time on stringification, A-Frame will only update in debug mode the component’s serialized representation in the actual DOM. Calling flushToDOM () will manually serialize the component’s data and update the DOM:
document.querySelector('[geometry]').components.geometry.flushToDOM();
Name | Description |
---|---|
enterVR | Switch to stereo render and push content to the headset. Needs to be called within a user-generated event handler like click . the first time a page enters VR. |
exitVR | Switch to mono renderer and stops presenting content on the headset. |
reload | Revert the scene to its original state. |
Name | Description |
---|---|
enter-vr | User has entered VR and headset started presenting content. |
exit-vr | User has exited VR and headset stopped presenting content. |
loaded | All nodes have loaded. |
renderstart | Render loop has started. |
Since <a-assets>
and <a-asset-item>
are nodes in A-Frame, they will emit
the loaded
event when they say they have finished loading.
Event Name | Description |
---|---|
loaded | All assets were loaded, or assets timed out. |
timeout | Assets timed out. |
<a-asset-item>
<a-asset-item>
invokes the three.js
FileLoader. We can use
<a-asset-item>
for any file type. When finished, it will set its data
member with the text response.
Event Name | Description |
---|---|
error | Fetch error. Event detail contains xhr with XMLHttpRequest instance. |
progress | Emitted on progress. Event detail contains xhr with XMLHttpRequest instance, loadedBytes , and totalBytes . |
loaded | Asset pointed to by src was loaded. |
<img>
Images are a standard DOM element so we can listen to the standard DOM events.
Event Name | Description |
---|---|
load | Image was loaded. |
HTMLMediaElement
Audio and video assets are HTMLMediaElement
s. The browser triggers
particular events on these elements; noted here for convenience:
Event Name | Description |
---|---|
error | There was an error loading the asset. |
loadeddata | Progress. |
progress | Progress. |
A-Frame uses these progress events, comparing how much time the browser buffered with the duration of the asset, to detect when the asset becomes loaded.
Here is an overview of animation attributes. We'll go into more detail below.
Attribute | Description | Default Value |
---|---|---|
attribute | Attribute to animate. To specify a component attribute, use componentName.property syntax (e.g., light.intensity ). | rotation |
begin | Event name to wait on before beginning animation. | '' |
delay | Delay (in milliseconds) or event name to wait on before beginning animation. | 0 |
direction | Direction of the animation (between from and to ). One of alternate , alternateReverse , normal , reverse . | normal |
dur | Duration in (milliseconds) of the animation. | 1000 |
easing | Easing function of the animation. There are very many to choose from. | ease |
end | Event name to wait on before stopping animation. | '' |
fill | Determines effect of animation when not actively in play. One of backwards , both , forwards , none . | forwards |
from | Starting value. | Current value. |
repeat | Repeat count or indefinite . | 0 |
to | Ending value. Must be specified. | None |
Begin
The begin
attribute defines when the animation should start playing.
This can either be a number, representing milliseconds to wait, or an event name to wait for. For example, we can define an animation that waits 2 seconds before scaling an entity.
<a-entity>
<a-animation attribute="scale" begin="2000" to="2 2 2"></a-animation>
</a-entity>
Or we can define an animation that waits for the parent element to trigger an
event named fade
before fading an entity.
<a-entity id="fading-cube" geometry="primitive: box" material="opacity: 1">
<a-animation attribute="material.opacity" begin="fade" to="0"></a-animation>
</a-entity>
// Trigger an event to begin fading.
document.querySelector('#fading-cube').emit('fade');
Direction
The direction
attribute defines which way to animate between the starting
value and the final value.
When we define an alternating direction, the animation will go back and forth
between the from
and to
values like a yo-yo. Alternating directions only
take affect when we repeat the animation.
Value | Description |
---|---|
alternate | On even-numbered cycles, animate from from to to . On odd-numbered cycles, animation from to to from |
alternate-reverse | On odd-numbered cycles, animate from from to to . On even-numbered cycles, animation from to to from |
normal | Animate from from to to . |
reverse | Animate from to to from . |
Easing
The easing
attribute defines the easing function of the animation, which
defaults to ease
. There are too many easing functions to list, but we can
implicitly explain them.
One possible value is linear
. And the basic easing functions are ease
,
ease-in
, ease-out
, and ease-in-out
.
Then there are more groups of easing functions. The above basic easing
functions prefix each group of easing functions. The groups of easing functions
are cubic
, quad
, quart
, quint
, sine
, expo
, circ
, elastic
,
back
, and bounce
.
For example, the cubic
group of easing functions would consist of
ease-cubic
, ease-in-cubic
, ease-out-cubic
, ease-in-out-cubic
.
Fill
The fill
attribute defines the effect of animation when not actively in play.
Think of fill
as what values the animation sets on the entity before and/or
after each animation cycle. Below are the possible values for fill
and
their effects.
Value | Description |
---|---|
backwards | Before the animation starts, set the starting value to the from value. |
both | Combine the effects of both backwards fill and forwards fill. |
forwards | After the animation finishes, the final value will stay at the to value. The default fill. |
none | Before the animation starts, set the starting value to the initial value. After the animation finishes, reset the value to the initial value. |
Repeat
The repeat
attribute defines how often the animation repeats. We call each
repeat of the animation a cycle. Repeat can either be a number that counts down
on each animation cycle until it reaches 0
at which point the animation will
end, or we can set repeat
to indefinite
and the animation will loop
continuously until the animation is manually removed or stopped.
The <a-animation>
element emits a couple of events.
Event Name | Description |
---|---|
animationend | Emitted when the animation finishes. In case of repeats, emitted when the repeat count reaches 0 . Not emitted for indefinite repeats. |
animationstart | Emitted immediately when the animation begins playing. |
Primitives act as a convenience layer (i.e., syntactic sugar) primarily for
newcomers. Keep in mind for now that primitives are <a-entity>
s under the
hood that:
<a-box>
)Primitives are similar to prefabs in Unity. Some literature on the entity-component-system pattern refer to them as assemblages. They abstract the core entity-component API to:
<a-sky>
)Under the hood, this <a-box>
primitive:
<a-box color="red" width="3"></a-box>
represents this entity-component form:
<a-entity geometry="primitive: box; width: 3" material="color: red"></a-entity>
<a-box>
defaults the geometry.primitive
property to box
. And the
primitive maps the HTML width
attribute to the underlying geometry.width
property as well as the HTML color
attribute to the underlying
material.color
property.
It's possible that you must enable gamepadextentions. You could do that using this steps:
chrome://flags
about:config
opera:config
about:flags
The cursor is a specific application of the raycaster component in that it
When the mouse clicks, the closest visible entity intersecting the cursor, if any, will emit a click event. Note the cursor component only applies the raycasting behavior. To provide a shape or appearance to the cursor, you could apply the geometry and material components.
Event | Description |
---|---|
click | Emitted on both cursor and intersected entity if a currently intersected entity is clicked (whether by mouse or by fuse). |
fusing | Emitted on both cursor and intersected entity when fuse-based cursor starts counting down. |
mousedown | Emitted on both cursor and intersected entity (if any) on mousedown on the canvas element. |
mouseenter | Emitted on both cursor and intersected entity (if any) when cursor intersects with an entity. |
mouseleave | Emitted on both cursor and intersected entity (if any) when cursor no longer intersects with previously intersected entity. |
mouseup | Emitted on both cursor and intersected entity (if any) on mouseup on the canvas element. |
When not in VR mode, userHeight
translates the camera up to approximate average height of human eye level. The injected camera has this set to 1.6 (meters). When entering VR, this height offset is removed such that we used absolute position returned from the VR headset. The offset is convenient for experiences that work both in and out of VR, as well as making experiences look decent from a desktop screen as opposed to clipping the ground if the headset was resting on the ground.
When exiting VR, the camera will restore its rotation to its rotation before it entered VR. This is so when we exit VR, the rotation of the camera is back to normal for a desktop screen.