2016 will be the year of virtual reality. Oculus is coming, Lands End launched on Samsung Gear VR and Google is ramping up Cardboard. But how do we design these new experiences? We simply prototype them in Framer.
My background in architecture at the Delft University of Technology spiked my interest into VR. The architectural design process involves a lot of drawing, maquette making and model rendering. And it takes heavy spatial imagination to translate something from the screen to the real world. VR can narrow this spatial gap dramatically, so I started experimenting.
Those experiments resulted in
VRComponent – and it makes designing for VR easy and accessible. Get started with the template below.
VRComponent gives you a lot of behaviour for free and it works with modern mobile devices. It uses the device orientation (or mouse input) to manipulate the orientation of the environment, which you can set up with a simple cubemap. By default, it animates beautifully with momentum and spring physics. You don't have to be a 3D expert to get started, but some familiarity with Framer is helpful.
Framer is not a full 3D engine so there are limitations to what you can do with
VRComponent. This post takes you through the setup and the following concepts to design your VR experience:
- Create a panoramic environment
- Project layers over the environment
- Animate projected layers
- Line of sight
- Shifting the environment
- Interacting with layers
Create a panoramic environment
There are multiple ways of rendering a panoramic view.
VRComponent uses a cubemap to project the environment on the sides of a cube. The user is positioned in the center, while the orientation of the cube is fixed. Simply instantiate
VRComponent and a textureless cube pops up.
require "VRComponent"vr =
By specifying images for all six sides, the cube seems to be replaced by the new environment.
vr =front: "images/front.png"left: "images/left.png"right: "images/right.png"back: "images/back.png"top: "images/top.png"bottom: "images/bottom.png"
To map your environment, you can look for cubemap images online. The images from the examples have been made by Emil Persson.
In a virtual environment, each side is often named by the positive or negative X, Y, or Z axis:
- right — positive-x
- top — positive-y
- front — positive-z
- left — negative-x
- bottom — negative-y
- back — negative-z
Project layers over the environment
Layers in Framer are positioned with
y values, following the Cartesian coordinate system. Everything is measured relatively to the "start" of the canvas, which simply means top-left in Framer. Obviously, virtual reality has no top-left, so we'll need a different coordinate system.
An alternative to the Cartesian system is the Spherical coordinate system. Here, each position is described in space around a central origin.
heading has a polar angle from 0° to 360° where north is 0°
elevation has a zenith angle from -90° to 90° where horizon is 0°
distance defined in pixels
distance defaults to 1200, equal to perspective. When distance and perspective are equal, layers retain the same size they had before projecting.
layer =heading: 230elevation: 10vrprojectLayerlayer
To simplify setting the coordinates of layers, aim
VRComponent at the latest projected layer with this property:
vr.lookAtLatestProjectedLayer = true
Animate projected layers
Changes to the heading and elevation of projected layers, can be animated like any other numerical property.
layer =vrprojectLayerlayerlayeranimateproperties:heading: -30elevation: 5
When a layer is projected with a heading of 0°, animating to -30° will animate the layer to the left. Animating to 330° animates it to the right.
layer =heading: -30print layerheading# returns 330
Line of sight
To understand the direction the user is facing, imagine a vector (a line pointing in a direction) sticking out of the back of your mobile device.
VRComponent contains all information about the heading and elevation of this vector, as well as the tilt around its axis (from -180° to 180°). You can listen for orientation changes using
# direct access through propertyheading = vrheading# continues updatesvron EventsOrientationDidChangeheading = dataheadingelevation = dataelevationtilt = datatilt
The heading and elevation values are important to define what the user is looking at, and what part of the UI needs focus. Meanwhile, the tilt value can be used to keep layers aligned with the viewer.
Shifting the environment
You can overwrite the direction the user is facing, by changing the heading and elevation values of
VRComponent. Changing these values rotates the horizon around the user. On desktop this can be used to create beautiful cinematic transitions.
# instant changevr.heading = 180# animated changevranimateproperties:heading: 90
On mobile, you can temporarily override the elevation using an animation. When the animation is done, the horizon snaps back to the value from the gyroscope. Keep in mind that animating the elevation, shifts the horizon to an unnatural position, and this can be disorienting for the user.
Interacting with layers
Detecting clicks and taps is similar to what you already know. Keep in mind that layers are projected at a certain distance, so the actual size might be smaller than you'd expect. Make sure the hit areas are large enough.
The orientation layer on desktop blocks all interaction with the layers underneath. If this is a problem, you can disable the orientation layer. With the orientation layer disabled, you can still look around using your arrow keys.
vr.orientationLayer = false
Instead of using taps or clicks, you can experiment with alternative interaction patterns for VR. Here's a fun puzzle I made to explore a new VR interaction: look and stare to select. It works beautifully on iPhone.
I hope this post got you excited about designing for VR! If you missed it at the beginning, here's
VRComponent on GitHub. Over time you can expect more features, like stereoscopic VR to present different images to the left and right eye. Pull requests, issues or nice cubemaps are greatly appreciated.
If you have questions about VR, explorations or prototypes - please post them to our Facebook community. I'm excited to see what you dream up!