This paper presents some pre-visualization design methods for volumetric user interfaces and experiences within the larger scope of a virtual reality operating system.
A-Frame & ARjs with Urban Power 3D model
The below example shows using A-Frame together with ARjs to show an Urban Power 3D model (Havnegade in Næstved).
Please notice, that it is necessary to add a link to a JavaScript library containing the ARjs component.
The example should use a custom marker, but this doesn’t work!!! So just use a printout of one of the preset markers, when you test it.
Please use Firefox as browser, when you test it (also on your phone).
The model is not correctly positioned/rotated, so you must do that to make it show nicely. As the model is quite big, it can be necessary to step a bit back from the marker to show the model!!!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<html> <head> <title>ARjs with Urban Power model</title> <script src="https://aframe.io/releases/0.7.0/aframe.min.js"></script> </head> <!-- include ar.js for A-Frame --> <script src="https://jeromeetienne.github.io/AR.js/aframe/build/aframe-ar.js"></script> <body style='margin : 0px; overflow: hidden;'> <a-scene embedded arjs='sourceType: webcam;'> <a-assets> <a-asset-item id="havnegade" src="20180124_havnegade.gltf"> </a-asset-item> </a-assets> <!-- use your gltf model --> <a-entity gltf-model="#havnegade" position="0 0.5 0" rotation="0 -180 0" scale="0.01 0.01 0.01"></a-entity> <!-- define a camera which will move according to the marker position --> <a-marker-camera preset='custom' patternUrl='pattern-marker.patt'> </a-marker-camera> </a-scene> </body> </html> |
A-Frame & ARjs with basic 3D model
The below example shows using A-Frame together with ARjs to show a basic 3D model of a rocket.
Please notice, that it is necessary to add a link to a JavaScript library containing the ARjs component.
The example uses a standard marker called “Hiro”.
Please use Firefox as browser, when you test it (also on your phone).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<html> <head> <title>ARjs with basic 3D</title> <script src="https://aframe.io/releases/0.7.0/aframe.min.js"></script> ); </head> <!-- include ar.js for A-Frame --> <script src="https://jeromeetienne.github.io/AR.js/aframe/build/aframe-ar.js"></script> <body style='margin : 0px; overflow: hidden;'> <a-scene embedded arjs> <!-- create your content here. just a box for now --> <a-obj-model src="model.obj" mtl="materials.mtl" position="0 0.5 0" scale="0.3 0.3 0.3" /> <!-- define a camera which will move according to the marker position --> <a-marker-camera preset='hiro'></a-marker-camera> </a-scene> </body> </html> |
A-Frame – dynamic JavaScript, code part (.js)
The below example shows using A-Frame together with JavaScript.
The example shows, how to animate a sphere on a plane.
This is the JavaScript part.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
//creates shortcut for selecting DOM element $ = (queryString) => document.querySelector(queryString); //Change color of the sphere programmatically //without animation //$('a-sphere').setAttribute('color', 'blue'); /* //our callback function let count = 0; const animate = () => { //do something /console.log(count++); requestAnimationFrame(animate); } requestAnimationFrame(animate); */ //create a state variable for hue let hue = 0; /* Hue is one of the main properties (called color appearance parameters) of a color, defined technically (in the CIECAM02 model), as "the degree to which a stimulus can be described as similar to or different from stimuli that are described as red, green, blue, and yellow", (which in certain theories of color vision are called unique hues). read more at: https://en.wikipedia.org/wiki/Hue */ //function for changing color 60times a second const shiftHue = (hue) => (hue + 1) % 360; //modulus 360, så the value never goes over 360. //Change color of the sphere programmatically //with animation using javascript requestAnimationFrame() method which calls our animate() callback 60 times/sec //our callback function const animate = () => { //every frame we will create a new hue hue = shiftHue(hue); const color = `hsl(${hue}, 100%, 50%)`; //hue, saturation, light const variation = Math.sin(Date.now() / 1000); const position = `0 ${1.5 + variation} -4`; $('a-sphere').setAttribute('color', color); $('a-sphere').setAttribute('position', position); $('a-plane').setAttribute('rotation', `-90 ${120 * variation} 0`); $('a-plane').setAttribute('color', color); requestAnimationFrame(animate); }; //programmatic animation. //requestAnimationFrame() will fire the callback when the browser is ready //will do it 60 times/second requestAnimationFrame(animate); |
A-Frame – dynamic JavaScript, HTML part
The below example shows using A-Frame together with JavaScript.
The example shows, how to animate a sphere on a plane.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <script src="https://cdnjs.cloudflare.com/ajax/libs/aframe/0.7.1/aframe.js"></script> <title>Title</title> </head> <body> <!-- Setting a-sphere attributes(color and posistion) manually <a-scene> <a-sphere color="red" position="0 1.5 -2"></a-sphere> <! rotation is -90 because originally the plan is vertical and we want it horizontal e.g lying flat <a-plane width="10" height="10" position="0 0 -5" rotation="-90 0 0" color="black" ></a-plane> </a-scene> --> <!-- Now when we have our javascript we will set attributes programmatically from index.js Thus we will remove the color and position attributes from the a-sphere --> <a-scene> <a-sphere></a-sphere> <a-plane src="https://media.giphy.com/media/3o8doVAxrMjXbIHaU0/giphy.gif" width="8" height="8" position="0 0 -2" ></a-plane> </a-scene> <script src="index.js"></script> </body> </html> |
A-Frame – a-cursor without click
The below example shows using a-cursor with no click event, but with mouseenter & moveleave events, which will show/hide a text (“HELLO WORLD!”) hovering over a box.
Please notice, that it is necessary to add a link to a JavaScript library containing the text component, and that the component only works with A-Frame releases from 0.4.0 and below!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
<html> <head> <title>Demo a-cursor with no click</title> <script src="https://aframe.io/releases/0.4.0/aframe.min.js"></script> <script src="https://rawgit.com/bryik/aframe-bmfont-text-component/master/ dist/aframe-bmfont-text-component.min.js"></script> </head> <body> <a-scene> <a-assets> </a-assets> <a-box color="blue" width="1" height="1" position="0 10 0" rotation="0 0 0" scale="1 2.5 1"> </a-box> <a-entity scale="2 2 2" bmfont-text="text: HELLO WORLD!; color:white; size: 1.5; height: 0.5; opacity:0" position="-0.27 9.28 0.91"></a-entity> <a-camera position="0 7 5"> <a-cursor color="#FF0000" /> </a-camera> </a-scene> <script type="text/javascript"> var box = document.querySelector( 'a-box'); var text = document.querySelector( 'a-entity'); box.addEventListener( "mouseenter", function () { text.setAttribute("bmfont-text", { opacity: 1 }); }); box.addEventListener( "mouseleave", function () { text.setAttribute("bmfont-text", { opacity: 0 }); }); </script> </body> </html> |
A-Frame – a-cursor with click
The below example shows using a-cursor, where a click event will rotate a box. Mouseenter & moveleave events will scale the box up and down.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
<html> <head> <title>Demo a-cursor with click</title> <script src="https://aframe.io/releases/0.7.0/aframe.min.js"></script> </head> <body> <a-scene> <a-assets> </a-assets> <a-box color="blue" width="1" height="1" depth="1" position="0 10 0" rotation="45 45 45" scale="1 2.5 1"> <a-animation attribute="rotation" begin="click" repeat="3" to="0 360 0"></a-animation> </a-box> <a-camera position="0 7 5"> <a-cursor color="#FF0000" /> </a-camera> </a-scene> <script type="text/javascript"> var box = document.querySelector( 'a-box'); box.addEventListener( "mouseenter", function () { box.setAttribute("scale", { x: 0.5, y: 2, z: 5.9 }); }); box.addEventListener( "mouseleave", function () { box.setAttribute("scale", { x: 1, y: 2.5, z: 1 }); }); </script> </body> </html> |
Insert a logo in a 360 image
You make an 360 image, but want to hide the tripod, the artifacts of the stitching or just want to watermark your artwork with a mark of your own.
The simple way is to insert the text in a box in the bottom (~300px) of the image.

Thus it will cover the tripod etc. Due to the mapping of the image to a sphere the logo will be exposed to a spheric compression making it look “blown up”.

If you’re inclined to show off, you can also spend a little more time and make it look “awesome”, or, just pretend to have too much time on your hands.


Technique is shown in this video-tutorial.
A-Frame – controls
The below example shows using controls on a 3D model of Axeltorv (Næstved) in the .glTF format.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<html> <head> <title>Urban Power model - Axeltorv</title> <script src="https://aframe.io/releases/0.7.0/aframe.min.js"></script> <script src="https://rawgit.com/fernandojsg/aframe-teleport-controls/master/dist/aframe-teleport-controls.min.js"></script> </head> <body> <a-scene> <a-asset-item id="axeltorv" src="20180131_axeltorv.gltf"></a-asset-item> <a-entity gltf-model="#axeltorv" scale="0.1 0.1 0.1" rotation="-86 -133 174" position="-2.11 -9.05 -1.32"></a-entity> <a-entity id="cameraRig"> <a-entity id="head" camera wasd-controls look-controls></a-entity> <a-entity id="left-hand" teleport-controls="cameraRig: #cameraRig; teleportOrigin: #head;" gearvr-controls></a-entity> <a-entity id="right-hand" teleport-controls="cameraRig: #cameraRig; teleportOrigin: #head;" gearvr-controls></a-entity> </a-entity> <a-sky color="#599"></a-sky> </a-scene> </body> </html> |
A-Frame – 3D models
The below example shows a ready-made 3D model downloaded from Google Blocks – the 3D model is a rocket shown beside three primitives.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<head> <title>A-frame primitives & 3D object demo</title> <script src="https://aframe.io/releases/0.7.0/aframe.min.js"></script> </head> <body> <a-scene> <a-assets> <a-asset-item id="mtl" src="./materials.mtl"></a-asset-item> <a-asset-item id="obj" src="./model.obj"></a-asset-item> </a-assets> <a-sphere position="0 1.25 -5" radius="1.25" color="#EF2D5E"></a-sphere> <a-box position="-1 0.5 -3" rotation="0 45 0" width="1" height="1" depth="1" color="#4CC3D9"></a-box> <a-cylinder position="1 0.75 -3" radius="0.5" height="1.5" color="#FFC65D"></a-cylinder> <a-plane position="0 0 -4" rotation="-90 0 0" width="4" height="4" color="#7BC8A4"></a-plane> <a-sky color="#ECECEC"></a-sky> <a-entity obj-model="obj: #obj; mtl: #mtl;" position="5.395 1.892 -1.221" scale="1 1 1"> </a-entity> </a-scene> </body> |