HTML & Primitives
This section will go over the concepts of A-Frame’s primitive elements and their relation to the entity-component framework. If you’re looking for a guide on using HTML and primitives, check out the Building a Basic Scene guide.
A-Frame is based on top of HTML and the DOM using a polyfill for Custom Elements. HTML is the building block of the Web, providing one of the most accessible computing languages around. There are no installations or build steps required, creating with HTML involves just text in an HTML file and opening the HTML file in a browser. Since most of the Web was built on top of HTML, most existing tools and libraries work with A-Frame including React, Vue.js, Angular, d3.js, and jQuery.
If you don’t have too much experience with HTML, no problem! It’s fairly easy to pick up and perhaps even easier to grasp than 2D HTML. Once you pick up the general structure or syntax of HTML (opening tag, attributes, closing tag), then you’re good to go! Read an introduction to HTML on MDN.
While the HTML layer looks basic, HTML and the DOM are only the outermost abstraction layer of A-Frame. Underneath, A-Frame is an entity-component framework for three.js that is exposed declaratively.
A-Frame provides a handful of elements such as
primitives that wrap the entity-component pattern to make it appealing for
beginners. At the bottom of the documentation navigation sidebar, we can see
every primitive that A-Frame provides out of the box. Developers can create
their own primitives as well.
Below is the Hello, WebVR example that uses a few basic primitives. A-Frame provides primitives to create meshes, render 360° content, customize the environment, place the camera, etc.
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
- Have a semantic name (e.g.,
- Have a preset bundle of components with default values
- Map or proxy HTML attributes to component data
- Pre-compose useful components together with prescribed defaults
- Act as a shorthand for complex-but-common types of entities (e.g.,
- Provide a familiar interface for beginners since A-Frame takes HTML in a new direction
Under the hood, this
<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
property as well as the HTML
color attribute to the underlying
Primitives are just
<a-entity>s under the hood. This means primitives have
the same API as entities such as positioning, rotating, scaling, and attaching
Let’s attach community physics components to primitives. We include the source
for Don McCurdy’s
aframe-physics-system and attach
the physics components via HTML attributes:
If you are using A-Frame 1.5.0 or later:
aframe-physics-systemand you’re having issues, make sure you’re using THREE.BufferGeometry, not the now-deprecated THREE.Geometry. Recent versions of three.js rename generators such as PlaneBufferGeometry to just PlaneGeometry, but support the old name as an alias. More info on this GitHub issue.
We can register our own primitives (i.e., register an element) using
name is a string and must contain a dash (i.e.
object defining these properties:
|defaultComponents||Object specifying default components of the primitive. The keys are the components’ names and the values are the components’ default data.||
|mappings||Object specifying mapping between HTML attribute name and component property names. Whenever the HTML attribute name is updated, the primitive will update the corresponding component property. The component property is defined using a dot syntax
For example, below is A-Frame’s registration for the
var extendDeep = AFRAME.utils.extendDeep;
For example, Don McCurdy’s
aframe-extras package includes an
<a-ocean> primitive that wraps his
ocean component. Here is the definition
<a-ocean> primitive registered, we’d be able to create oceans using
a line of traditional HTML:
<a-ocean color="aqua" depth="100" width="100"></a-ocean>