AFrame for Over the air

Convert to Slide Deck

Length should be 15 minutes.

Hi, I’m Ada from Samsung.

I am really irritating at dinner parties.

I am perpetually bringing out VR headsets and trying to get people to have a go.

I love building and showing off cool VR demos.

Now it is now easier than ever before with A-Frame.

When they do give it a go though

my favourite moment is when they get wowed by the immersion and they make this face:

Getting started with WebVR

Introduction to A-Frame

Ada Rose Edwards - Samsung Research UK


I love that face.

My goal is to get you building stuff with A-Frame

so you can make your friends and relatives have the same

awed expression


What is A-Frame

A-Frame a is a JavaScript library to abstract away the difficult and the rote parts of Virtual Reality.

A-Frame is built on top of another library called THREE.js

It also includes the WebVR polyfill.

The WebVR polyfill allows all smartphones to be VR capable with Google Cardboard

THREE.js provides a nice way to work with 3D rendering.

A-Frame simplifies everything and abstracts away the more difficult bits.

Allowing us to get started straight away!


Why do I like A-Frame?

A-Frame allows you to compose scenes with 3D models, Videos, Audio, Images by writing html.

It handles a lot of the heavy lifting and edge cases.

The fundamentals of a scene are already set up so don’t need to be written out again and again and again

I can get started making something straight away with no faffing about.


Composing scenes with A-Frame

A-Frame is webby.

Well for one it looks like html and can be written directly into your markup.

It gives new html elements for building virtual reality

Who here has built a website by typing out html before?

It is much the same. Like HTML you can do an awful lot without writing a single line of javascript. But you can still use JavaScript to add extra functionality of you want.

It is also modular and extensible.

Modular means that I can write a component. For example. A component to give a heads up display or fancy lighting.

Then anyone can include it in their scenes without needing to write complex JavaScript.

It is extensible because my components will be based on other A-Frame components and you can release components that depend on mine.

You are not required to write a single line of JavaScript unless you want to make your own components.

		<script src="js/a-frame.js"></script>
			<a-sphere position="0 1.25 -1" radius="1.25" color="#EF2D5E"></a-sphere>
			<a-box position="-1 0.5 1" rotation="0 45 0" color="#4CC3D9"></a-box>
			<a-cylinder position="1 0.75 1" radius="0.5" color="#FFC65D"></a-cylinder>
			<a-plane rotation="-90 0 0" width="4" height="4" color="#7BC8A4"></a-plane>
			<a-sky color="#ECECEC"></a-sky>


This html from the previous slide gives us this.

But A-Frame gives us lots of hidden extras, all the basics to get started:

All of this functionality can be overridden if you don’t like it or if you want more control.

The Gear VR does not run VR websites out of the box it needs to be turned on.

This is a bit annoying and confusing because my demos wouldn’t work and I didn’t know why.

Testing if WebVR is available

Now your headset is set up to make the most of VR in the web!!!

Try that previous url again and you will see a cool demo, or try out any of the A-Frame demos.

Now we have WebVR set up lets actually build something.

To enable webvr in GearVR open this URL in the WebVR browser



Actually building something

The first thing a lot of people build is a 360 degree photo/video Viewer.

It makes a great first project as it has very few components/

So we’ll look at that first as it is a very simple demo.

Here I have some images I want to use.

These go into the a-assets tag, this tells a-frame to preload these for later.

We override the camera, by defining our own with the keyboard controls disabled. We don’t want too let the user move around in the scene.

The final piece is the sky, the sky is an evenly lit inside out sphere. We give it the image we want to display and it shows it off.

This has all the features we want from a 360 image viewer, you can rotate the camera, view it immersively in vr and all in 7 lines of html

The image itself looks like this:

		<img id="img1" src="a-frame-assets/SAM_100_0042_SMALL.jpg" />

	<a-camera wasd-controls="enabled: false;"></a-camera>

	<a-sky src="#img1"></a-sky>


The image itself looks like this:

A 360 image taken with the gear VR

I took it with my 360 camera (no reason to post this I just think it is adorable):

The adorable Gear360

Adding some interactivity

If you are comfortable writing JavaScript and want to do something more advanced

You can, you can use JavaScript to control a-frame just like you would use it on normal html

Here I have written a small script to rotate through some images whenever I click.

		<img id="img1" src="a-frame-assets/SAM_100_0046_SMALL.jpg" />
		<img id="img2" src="a-frame-assets/SAM_100_0063_SMALL.jpg" />
		<img id="img3" src="a-frame-assets/SAM_100_0042_SMALL.jpg" />

	<a-camera wasd-controls="enabled: false;"></a-camera>
	<a-sky src="#img1"></a-sky>


	var index = 0;
	var images = document.querySelectorAll('a-assets img');
	var sky = document.querySelector('a-sky');
	window.addEventListener('click', function () {
		index = (index + 1) % images.length;
		sky.setAttribute('src', '#' + images[index].id);

Demo 360 Slideshow

Introduce some tools for making 3d content

Enough showing you my holiday photos, what if you want to actually include a more complex 3D object:

A-Frame comes with a whole bunch of geometric primitives.

By one sided I mean that if you were to view it from the back you don’t see anything.

One Sided

In 3D unless specified otherwise flat shapes are one sided

By one sided I mean that if you were to view it from the back you don’t see anything.

But there is only so much you can do with primitives.

We can make them a little more complex by attatching them together.

Models from Primitives

By making one object a child of another they become attached together.

The child is transformed in the same way as the parent.

By transformed I mean the way it is scaled, rotated or positioned.

This keeps them stuck together.

	<a-box position="0 2 0" color="red">

		<!-- This blue box is a child of the red box -->
		<a-box position = "0.5 0.5 0.5" color="blue"></a-box>

		<!-- Spin the red box -->
		<a-animation repeat="indefinite" attribute="rotation" easing="linear" to="0 360 0" dur="2000"></a-animation>

Scene Graphs

This behaviour is known as a scene graphs

It creates a heirarchy of items in the scene. So you can reuse models and attach them to other objects.

E.g. A model bus only needs one chair which can then be reused and attatched to the bus again and again.

This is good because each unique model is expensive but reusing it is cheap.

The example behind me is just a more elaborate version of the last slide.

It is being transformed elaborately


So I am going to step aside for a bit.

To leave you to play with some demos and get some inspiration.

And ask me some questions.

Then in about 10 minutes I will then run through some of my favourite examples of UI interactions.

Docs -

Interactivity Workspace -

Fancy Material Workspace -

Physics Workspace -

Making new components

If you do not find a component which does what you want.

You can make your own components as well.

There is a lot to take in when extending A-Frame for the first time.

I was totally lost.

I reached out to A-Frame community by joining the A-Frame slack channel.

They are really friendly and very helpful.

I asked where to begin and some of the best advice I recieved was to create your own component.

This seemed daunting at first but once I got stuck in and asked for some help it began to make sense.

This really allowed me to get to grips with how A-Frame works.

What can Components do?

The most fundamental element in a-frame is the <a-entity>

An <a-entity> is an empty THREE.js group with no geometry or material.

Components are the discreet bits of logic which power A-Frame.

They provide the interface between the mark up (HTML) and the 3D rendering engine THREE.js

They are entity agnostic.

They do not care what they are attatched to.

For example the position component just sets the objects position in 3D space.

The rotation component rotates the entity by an angle in degrees.

More complex components such as geometry or material have properties defined like the style attribute;


<a-entity position="0 1 0"></a-entity>

<a-entity position="0 1 0" rotation="0 90 0"></a-entity>

<a-entity position="0 1 0" rotation="0 90 0" geometry="primitive: box; width: 3; height: 2; depth: 2;"></a-entity>

<a-entity position="0 1 0" rotation="0 90 0" geometry="primitive: box; width: 3; height: 2; depth: 2;" material="color: red;"></a-entity>

Reusing Components

They are usually totally agnostic to what they get attatched to.

For example we can take the ‘wasd-controls’ off the camera and attach them to our racing ship from earlier.


	<!-- controls  disabled -->
	<a-camera wasd-controls="enabled: false;"></a-camera>

	<!-- controls  enabled -->
	<a-entity wasd-controls="enabled: true;">
		<a-obj-model src="#Feisar-ship-obj" mtl="#Feisar-ship-mtl" id="ship"></a-obj-model>


Component move demo

As you can see now the camera does not move but the ship does

I’m beginning to think we could do something cool with this…

Making a new component

A component has two parts a schema and set of call back functions.

The schema defines what data gets passed into the component from the attributes defined in the markup.

The data is passed into init and update functions. It is also available on in any of the component’s functions.

These are functions which are called during the component’s life cycle.

you can call any of these by going el.components.myComponent.foobar();

function name When called
init When the component is first used per element
update After init and whenever the data is changed
tick Once per frame
remove when the component needs to be torn down
foobar function available to be called later

This example is a real example taken from the a-frame source code.

It is the position component it shows that components should be small, single use and reusable.

Think the UNIX philosiphy.

	// Simple one property schema
	// <a-entity component1="1 2 3"></a-entity>
	registerComponent('component1', {
		schema: {type: 'vec3'}

	// Multi-property property schema
	// <a-entity component2="oranges: blah; someEl: #thatEl;"></a-entity>
	registerComponent('component2', {
		schema: {
			apples: {default: 2}, // implied to be a number
			oranges: {default: ''} // implied to be a string
			someEl: {type: selector}

	// Built in types:
	// array, boolean, color, int, number, selector, selectorAll, src, string, time, vec2, vec3, vec4

	registerComponent('component2', {
		schema: {},
		init: function () {

			// Called only once when component initialised
			this;            // <= the component;       // <= the data from the dom in the format defined by the schema
			this.el;         // <= the DOM element
			this.el.object3D // <= The THREE.js 3D model
		update: function () {
			// Called after init and whenever attributes on the element are changed
		tick: function () {
			// Called once per frame
		remove: function () {
			// Use this to undo the effects of the component
			// Called when the component is removed
			// also when the attatched el is deleted.
// Copy-pasted from the A-Frame source code.

registerComponent('position', {
  schema: {type: 'vec3'},

  update: function () {
    var object3D = this.el.object3D;
    var data =;
    object3D.position.set(data.x, data.y, data.z);

Be small, single use and reusable.
The unix philosiphy: "Do one thing and do it well."


Primitives are just a-entitys with a bunch of preset components.

For example this is a very large plane which looks like an ocean.

It uses 3 components, geometry, rotation and material

The mappings section allow easy ways to control some comoonents.

// <a-ocean-plane width="100" height="100"></a-ocean-plane>
AFRAME.registerPrimitive('a-ocean-plane', {
	defaultComponents: {
		geometry: {
			primitive: 'plane',
			height: 10000,
			width: 10000
		rotation: '-90 0 0',
		material: {
			shader: 'standard',
			color: '#8ab39f',
			metalness: 1,
			roughness: 0.2,
			opacity: 0.8
	mappings: {
		width: 'geometry.width',
		height: 'geometry.depth',
		color: 'material.color',
		opacity: 'material.opacity'