Hi! In this tutorial, we will learn how to make a 3D object that can be clicked on. This tutorial is for my Mobile VR series, so it is more geared toward mobile devices but is still compatible with other devices using a few tweaks.
Getting Started
I use PhoneGap to prototype my apps but if you just want the code you can skip those steps.
First, create a new project and inside its index.html paste this into it:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width"> <title>VR Button</title> <script type="text/javascript" src="cordova.js"></script>//only needed for phonegap <script src="https://aframe.io/releases/0.8.0/aframe.min.js"></script> </head> <body> <a-scene> <a-box id="boxId" position="0 0.5 -3" rotation="0 45 0" color="blue"></a-box> <a-sky color="#ECECEC"></a-sky> <a-camera position="0 1.6 0"></a-camera> </a-scene> </body> </html>
This is the basic program that we are going to be working with. In it, we have a single cube, a sky, and a camera.
Cursor
The first thing we need to do is to define a cursor. It’s basically a laser pointer that goes out of the object it is in and returns data about the shapes it intersected. For mobile, we put one in the camera object like this:
<a-camera position="0 1.6 0"> //we put it in the camera tag so it will rotate with the camera <a-entity cursor="fuse: false" position="0 0 -1" geometry="primitive:ring; radiusInner: 0.02; radiusOuter: 0.03" material="color: black; shader: flat"></a-ring> </a-camera>
What we just did was put a ring object in front of our camera and we defined it as a cursor. The ring will now hover in front of the camera and act like a crosshair for the cursor.
AFrame + JavaScript
When using javascript along with AFrame you need to make sure that the javascript doesn’t start running until AFrme is done initializing. We do this by creating an AFrame component:
<script type="text/javascript"> AFRAME.registerComponent('startButton',{ init: function () { //all code here } }); </script>
And then we use it in a-scene tag like this <a-scene startButton>
Button
We are going to be using a cube as our button, for this example we want it to turn red when we click on it, and later we will add a feature so it will turn green when we hover over it. There are two ways we could do this, with AFrame animations, or with javascript. For this tutorial, we will use javascript because it can be used for things other than color changing. What we are going to do is add an event listener to our cube. The cursor comes with five events: mousedown
, mouseup
, mouseenter
, mouseleave
, and click
.
First, add an id to the <a-box> tag. Then, we will use mousedown and mouseup so that when we click and hold on our cube it turns green.
<script type="text/javascript"> FRAME.registerComponent('startButton', { init: function () { var cube = document.querySelector("#boxId"); cube.addEventListener("mousedown",function(evt){ cube.setAttribute('material', 'color',"red"); }); cube.addEventListener("mouseup",function(evt){ cube.setAttribute('material', 'color',"blue"); }); } }); </script>
Now If we want to be fancy, we can make it so that when you hover over the cube it turns green, and we do this by using mouseenter and mouseleave:
<script type="text/javascript"> AFRAME.registerComponent('startButton', { init: function () { var cube = document.querySelector('a-scene').sceneEl.querySelector("#boxId"); cube.addEventListener("mousedown", function (evt) { cube.setAttribute('material', 'color', 'red'); }); cube.addEventListener("mouseup", function (evt) { cube.setAttribute('material', 'color', 'green');//we want to change this from "blue" to "green" to avoid some bugs }); cube.addEventListener("mouseenter", function (evt) { cube.setAttribute('material', 'color', 'green'); }); cube.addEventListener("mouseleave", function (evt) { cube.setAttribute('material', 'color', 'blue'); }); } }); </script>
And there you go! You should now have a button. For more info on cursor and how to use it on other devices, check out the AFrame docs.