Web developers around the world don’t need to go out and learn entirely new languages or a game engine like Unity or Unreal Engine to start developing virtual reality. There are various ways to start experimenting with VR on the web today and the A-Frame framework is one of the easiest ways to get started.
What is A-Frame?
A-Frame is an open source framework for creating WebVR experiences using custom HTML elements. These elements use three.js and WebGL to create VR-enabled elements in a scene, without requiring developers to learn lower level APIs such as WebGL in order to build simple experiences for VR.
The next — and very important — question most likely to be asked next would be “is A-Frame cross-browser compatible?”. Surprisingly, A-Frame experiences work well on a variety of platforms, with the 3D scene (without VR) being visible as a fallback as long as the browser is WebGL compatible. This means Chrome, Firefox, Edge and Opera all show an interactive 3D version of the experience for the desktop. For a VR experience, an Oculus Rift can be connected to WebVR enabled versions of some browsers to bring in VR compatibility (see links below under “What You’ll Need”).
In terms of smartphones, modern smartphones within the last two generations that run iOS and Android are best (iPhone 6 and up, Samsung Galaxy S6 and up, my HTC One M9 works well). Most of these also support virtual reality when inserted into a Google Cardboard headset, so VR-compatibility can actually be higher and easier to manage than trying to get VR working on your desktop!
What You’ll Need
To follow along and try out A-Frame yourself, you will need the following:
- For a basic non-VR experience — A WebGL enabled browser as mentioned above.
- For a desktop VR experience —
- For a mobile VR experience —
- Most modern smartphones will be capable of at least showing the scene and allowing you to look around in a semi-VR view (one without the headset itself but where moving the phone moves your view around).
- A Google Cardboard or Gear VR headset.
To get started, head to A-Frame’s Getting Started page. The A-Frame team have provided various options for experimenting with A-Frame, including CodePen snippets, an npm build, a downloadable or CDN available JS file of the framework, and a boilerplate with HTML and a local dev server as a guide to best practice. To keep things as simple as possible, we will be downloading and working directly from the A-Frame boilerplate.
Extract the boilerplate wherever you prefer to have web projects on your system. It does not necessarily need to be running on a local web server. The boilerplate uses A-Frame from their CDN, so it is mainly the
index.html file that we are after. The
package.json provides an npm based local web server for testing, we will use this in this article — however, it is not necessary to test this out.
Running Our Local Server
As mentioned above, the A-Frame Boilerplate comes with its own local web server ready for use. While this isn’t always necessary in order to test your A-Frame scenes, it is good practice to do so and can reduce confusion when it comes to various cross-origin policy issues that often arise when it comes to running webpages via the file system on your computer.
To run the local web server, go to the folder with your boilerplate project inside your Terminal/Command Prompt and run the following:
npm install && npm start
This will install all the necessary files for the web server and then run it for you. After this point, if you ever want to run the server again, just run
Upon running the local web server, it should automatically open up our web browser and load our boilerplate webpage. It comes with LiveReload — which means that it will automatically refresh whenever you make changes.
If you need to open the webpage on a different device, or if it does not open automatically after you’ve run the local web server, you can open it by going to
http://localhost:3000 in your browser or
http://192.168.0.1:3000, where that IP address is the IP address of your computer.
The initial scene you should see looks like so:
Building a New Scene
Let’s clean up the boilerplate code and remove everything within the
<body> tag apart from
<a-scene>. All of our A-Frame elements will be placed within this
<!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <title>Our First A-Frame Experience</title> <script src="https://aframe.io/releases/0.2.0/aframe.min.js"></script> </head> <body> <a-scene> </a-scene> </body> </html>
A-Frame comes with a set of primitives which provide us a series of commonly used elements for VR scenes. Let’s add a few of our own to build up a custom scene.
Setting Up Our Sky
Every scene needs a sky (or background of some kind). This can be either a flat color, or a panoramic, equirectangular image. The primitive for this is
The code for a sky with a single, flat color looks like so:
<a-scene> <a-sky color="#C500FF"></a-sky> </a-scene>
That creates a lovely and natural bright fuchsia sky for our scene:
As glorious as that sky is, it will look better with a panoramic 360 image. One nice spot to find skyboxes you can use to experiment is Flickr. There are a range of equirectangular photos here that are provided with a licence that will allow you to reuse them.
I went onto Flickr and found the following photo from Luca Biada which does require attribution in order to be used in a project (always check the licence terms!):
When we place this into our scene using the following code:
<a-scene> <a-sky src="street.jpg"></a-sky> </a-scene>
We get a 360 background of that scene:
Adding a Box
Now we have a scene, lets add some elements into it. Using the
<a-box> primitive, we can place cubes and boxes into our scene. The following code adds an orange box onto the road in our scene:
<a-box color="#B76705" depth="2" height="2" width="4" position="0 0 -1.25"></a-box>
color attribute works the same way as our skybox, setting up the texture color for our box element. We then have attributes for
width which give it its shape. Our box is 2 x 2 x 4, which makes it a wide box which will look vaguely like a box car when placed on the road. To place it in different positions in the scene, we can move its position using the
position attribute. That attribute takes three values, one for each axis:
x y z.
Our box with the code above, looks like so in our scene:
Adding Some Cylinders
Now we will add some extra street poles into the scene using the cylinder primitive —
<a-cylinder color="#1E130E" height="40" radius="0.5" position="-40 0 -8"></a-cylinder>
position attributes work in the same way as our box, however we have two new attributes —
radius which set the height and radius respectively for our cylinder. Here’s our scene with a subtle new pole:
It is incredibly easy to scale this idea, so with the following code, we can add a whole row of poles:
<a-cylinder color="#1E130E" height="40" radius="0.5" position="-40 0 -8"></a-cylinder> <a-cylinder color="#1E130E" height="40" radius="0.5" position="-10 0 -8"></a-cylinder> <a-cylinder color="#1E130E" height="40" radius="0.5" position="20 0 -8"></a-cylinder> <a-cylinder color="#1E130E" height="40" radius="0.5" position="50 0 -7"></a-cylinder>
Which looks like so:
Cylinders actually have a whole range of other options in A-Frame, feel free to explore those options in their Cylinder docs.
Adding a sphere
Another pretty common shape to include in a 3D space is a sphere. We can create spheres using the
<a-sphere> primitive like so:
<a-sphere color="#000000" radius="2" position="0 15 20"></a-sphere>
That code is pretty straight forward and creates a creepy black sphere floating in the sky behind us:
Adding Textures Using Assets
We can add textures to our primitives like the box, cylinder and sphere via the
<a-assets> tag. This sets up the A-Frame asset management system, which gives us the ability to define assets and then use them on our shapes. This is the recommended way to texture your scene.
I downloaded and adjusted a simple (but very cool) repeating pattern by Carlos Aguilar from Subtle Patterns. We can add that asset into our scene like so:
<a-assets> <img id="darktexture" src="blacktexture.png"> </a-assets>
id gives us a name to use when referring to our texture and using it on objects in our scene. The
src attribute tells A-Frame which image we want. To give an object in our scene that texture, we can include the texture within the object’s
src attribute, using a hash before the texture’s ID:
<a-sphere src="#darktexture" radius="2" position="0 15 20"></a-sphere>
That gives our random, spooky sphere in the sky a nicer and rather sci-fi looking texture:
To see these experiences in VR, you will either need an Oculus Rift connected to your PC or you will need a modern smartphone! The smartphone option is the easiest for most. If you don’t have a VR headset, when you go to the scene on your smartphone you will still see everything and can look around by moving your phone about:
If you have a Google Cardboard headset to use with your phone, you can click the VR icon on the bottom right corner to enter VR view:
Try It In Action
If you’d like to have a go at the A-Frame street demo we put together in this tutorial, you can see it right here — A-Frame Street Demo.
When it comes to WebVR, A-Frame is an incredibly simple and easy to use framework to put together VR experiences that are relatively cross-browser compatible. There is a whole lot more that can be done with A-Frame and I can’t wait to explore more of it in future articles here at SitePoint.
If you are a fan of WebVR, we covered how to build virtual reality in VR with Primrose and WebVR last week, definitely check that out! Primrose is another exciting WebVR framework aimed at productivity applications. Elio Qoshi also wrote about the recent WebVR 1.0 API Draft Proposal here at SitePoint which is worth a read if you are working with WebVR.
If you’ve used A-Frame for your own VR web experience, I’d love to see what you put together! Let me know in the comments below, or get in touch with me on Twitter at @thatpatrickguy.