Exercise 1: Hello World

A-Frame uses standard HTML with the a-frame.js library. Here’s a quick example to get us started.

<!DOCTYPE html>
<html lang="en">

<head>
    <title>Hello VR World!</title>
    <script src="https://aframe.io/releases/0.9.2/aframe.min.js"></script>
</head>

<body>
    <a-scene background="color: #FAFAFA">
      <a-box position="-1 0.5 -3" rotation="0 45 0" color="#4CC3D9" shadow></a-box>
      <a-sphere position="0 1.25 -5" radius="1.25" color="#EF2D5E" shadow></a-sphere>
      <a-cylinder position="1 0.75 -3" radius="0.5" height="1.5" color="#FFC65D" shadow></a-cylinder>
      <a-plane position="0 0 -4" rotation="-90 0 0" width="4" height="4" color="#7BC8A4" shadow></a-plane>
    </a-scene>
</body>

</html>

Exercise 2: 360 image

Now let’s bring in an image as a backdrop. Background images must be in a specific image projection called Equirectangular, here’s what can be found at Flickr when you search for Equirectangular

Download these background images for examples:
city.jpg
rep-square.jpg
opera.jpg
hamalir.jpg

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>360° Image</title>
    <meta name="description" content="360° Image Gallery - A-Frame">
    <script src="https://aframe.io/releases/0.9.0/aframe.min.js"></script>
  </head>
  <body>
    <a-scene>
      <a-assets>
        <img id="opera" crossorigin="anonymous" src="images/opera.jpg">
      </a-assets>

      <!-- 360-degree image. -->
      <a-sky id="image-360" radius="10" src="#opera"></a-sky>
      <!-- Camera + cursor. -->
      <a-entity id="camera" camera look-controls>
        <a-cursor id="cursor"></a-cursor>
      </a-entity>
    </a-scene>
  </body>
</html>

Exercise 3: Adding 3D Models

A-Frame allows use to import 3D Models into our environment. The models for your environment can be build from scratch in a modeling program like Blender, Maya or you could use an existing model in the following formats: glft, obj

Where to Find Models

Places to find 3D models include:

Download this ant model and forest background for this example.

<!DOCTYPE html>
<html lang="en">

<head>
    <title>Exercise-3</title>
    <script src="https://aframe.io/releases/0.9.2/aframe.min.js"></script>
</head>

<body>
    <a-scene>
        <a-assets>
            <a-asset-item id="trex" src="../images/trex.obj"></a-asset-item>
            <img id="forest" crossorigin="anonymous" src="../images/forest.jpg">
        </a-assets>
        <a-sky id="image-360" radius="10" src="#forest"></a-sky>
        <a-plane position="0 -6 0" rotation="-90 0 0" width="4" height="4" color="#7BC8A4" shadow></a-plane>
        <a-entity obj-model="obj: #trex;" scale="0.008 0.008 0.008" position="-3 -4 -5" material="color: brown" rotatation=""></a-entity>
    </a-scene>
</body>

</html>

Exercise 4: 360 Images with Buttons

https://aframe.io/docs/0.9.0/guides/building-a-360-image-gallery.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>360° Image Gallery</title>
    <meta name="description" content="360° Image Gallery - A-Frame">
    <script src="https://aframe.io/releases/0.9.0/aframe.min.js"></script>
    <script src="https://unpkg.com/aframe-event-set-component@5/dist/aframe-event-set-component.min.js"></script>
    <script src="https://unpkg.com/aframe-layout-component@5.3.0/dist/aframe-layout-component.min.js"></script>
    <script src="https://unpkg.com/aframe-template-component@3.2.1/dist/aframe-template-component.min.js"></script>
    <script src="https://unpkg.com/aframe-proxy-event-component@2.1.0/dist/aframe-proxy-event-component.min.js"></script>
  </head>
  <body>
    <a-scene>
      <a-assets>
        <img id="city" crossorigin="anonymous" src="https://cdn.aframe.io/360-image-gallery-boilerplate/img/city.jpg">
        <img id="city-thumb" crossorigin="anonymous" src="https://cdn.aframe.io/360-image-gallery-boilerplate/img/thumb-city.jpg">
        <img id="cubes-thumb" crossorigin="anonymous" src="https://cdn.aframe.io/360-image-gallery-boilerplate/img/thumb-cubes.jpg">
        <img id="sechelt-thumb" crossorigin="anonymous" src="https://cdn.aframe.io/360-image-gallery-boilerplate/img/thumb-sechelt.jpg">
        <audio id="click-sound" crossorigin="anonymous" src="https://cdn.aframe.io/360-image-gallery-boilerplate/audio/click.ogg"></audio>
        <img id="cubes" crossorigin="anonymous" src="https://cdn.aframe.io/360-image-gallery-boilerplate/img/cubes.jpg">
        <img id="sechelt" crossorigin="anonymous" src="https://cdn.aframe.io/360-image-gallery-boilerplate/img/sechelt.jpg">

        <!-- Image link template to be reused. -->
        <script id="link" type="text/html">
          <a-entity class="link"
            geometry="primitive: plane; height: 1; width: 1"
            material="shader: flat; src: ${thumb}"
            event-set__mouseenter="scale: 1.2 1.2 1"
            event-set__mouseleave="scale: 1 1 1"
            event-set__click="_target: #image-360; _delay: 300; material.src: ${src}"
            proxy-event="event: click; to: #image-360; as: fade"
            sound="on: click; src: #click-sound"></a-entity>
        </script>
      </a-assets>

      <!-- 360-degree image. -->
      <a-sky id="image-360" radius="10" src="#city"
             animation__fade="property: components.material.material.color; type: color; from: #FFF; to: #000; dur: 300; startEvents: fade"
             animation__fadeback="property: components.material.material.color; type: color; from: #000; to: #FFF; dur: 300; startEvents: animationcomplete__fade"></a-sky>

      <!-- Image links. -->
      <a-entity id="links" layout="type: line; margin: 1.5" position="0 -1 -4">
        <a-entity template="src: #link" data-src="#cubes" data-thumb="#cubes-thumb"></a-entity>
        <a-entity template="src: #link" data-src="#city" data-thumb="#city-thumb"></a-entity>
        <a-entity template="src: #link" data-src="#sechelt" data-thumb="#sechelt-thumb"></a-entity>
      </a-entity>

      <!-- Camera + cursor. -->
      <a-entity id="camera" camera look-controls>
        <a-cursor
          id="cursor"
          animation__click="property: scale; startEvents: click; from: 0.1 0.1 0.1; to: 1 1 1; dur: 150"
          animation__fusing="property: fusing; startEvents: fusing; from: 1 1 1; to: 0.1 0.1 0.1; dur: 1500"
          event-set__mouseenter="_event: mouseenter; color: springgreen"
          event-set__mouseleave="_event: mouseleave; color: black"
          raycaster="objects: .link"></a-cursor>
      </a-entity>
    </a-scene>
  </body>
</html>

Exercise 5: Animation

https://aframe.io/docs/0.9.0/components/animation.html

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>360° Image Gallery</title>
    <meta name="description" content="360° Image Gallery - A-Frame">
    <script src="https://aframe.io/releases/0.9.0/aframe.min.js"></script>
</head>

<body>
    <a-scene>
      <a-assets>
        <img id="opera" crossorigin="anonymous" src="../images/opera.jpg">
        <a-mixin id="image" geometry="height: 2; width: 2"></a-mixin>
        <a-mixin id="toggleVisible" animation="property: visible; from: false; to: true; dur: 1" visible="false"></a-mixin>
        <a-mixin id="moveUpDown" animation="property: position; to: 0 2 0; loop: true; dur: 1000; dir:alternate"></a-mixin>
        <img id="ring1" src="../images/ring1.png">
        <img id="schematic1" src="../images/schematic1.png">
      </a-assets>

      <a-entity id="schematic-1" position="0 0 -3">
              <a-image mixin="image" src="#ring1" position="-2 0 0" scale="0.7 0.7 0.7" animation="property: rotation; to: 0 360 0; loop: true; dur: 10000"></a-image>
              <a-image mixin="image moveUpDown" src="#schematic1"  animation="delay: 200; easing:easeInOutSine"></a-image>
          </a-entity>


          <a-entity
            geometry="primitive: box"
            material="color: red"
            position="2 0 -3"
            animation__mouseenter="property: components.material.material.color; type: color; to: blue; startEvents: mouseenter; dur: 500";
            animation__mouseleave="property: components.material.material.color; type: color; to: red; startEvents: mouseleave; dur: 500";></a-entity>
      <!-- 360-degree image. -->
      <a-sky id="image-360" radius="10" src="#opera"></a-sky>
      <!-- Camera + cursor. -->
      <a-entity id="camera" camera look-controls wasd-controls>
        <a-cursor id="cursor"></a-cursor>
      </a-entity>
    </a-scene>
</body>

</html>

Exercise 6: Text in VR

This example has text in it:
https://aframe.io/docs/0.9.0/components/text.html
and the code can be found here:
https://github.com/haigarmen/vrdining/blob/master/06/index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>360° Image Gallery</title>
    <meta name="description" content="360° Image Gallery - A-Frame">
    <script src="https://aframe.io/releases/0.9.0/aframe.min.js"></script>
    <script src="https://unpkg.com/aframe-event-set-component@5/dist/aframe-event-set-component.min.js"></script>
    <script src="https://unpkg.com/aframe-layout-component@5.3.0/dist/aframe-layout-component.min.js"></script>
    <script src="https://unpkg.com/aframe-template-component@3.2.1/dist/aframe-template-component.min.js"></script>
    <script src="https://unpkg.com/aframe-proxy-event-component@2.1.0/dist/aframe-proxy-event-component.min.js"></script>
  </head>
  <body>
    <a-scene>
      <a-assets>
          <img id="tsitsernakaberd" crossorigin="anonymous" src="../images/tsitsernakaberd_2.jpg">
      </a-assets>

      <!-- 360-degree image. -->
      <a-sky id="image-360" radius="10" src="#tsitsernakaberd"></a-sky>

      <a-entity text="color: white; align: center; font: aileronsemibold;
              value: Welcome to " scale="3 3 3" position="0 1.6 -2" geometry="primitive: plane; width: auto; height: auto" material="transparent: true; opacity: 0.25"
></a-entity>
      <a-entity text="color: white; align: center; font: aileronsemibold; value: TSITSERNAKABERD" scale="7 7 7" position="0 1.4 -2"></a-entity>
      <!-- Camera + cursor. -->
      <a-entity id="camera" camera look-controls wasd-controls position="0 1.6 0" >
      <!--         <a-cursor
          id="cursor"
          animation__click="property: scale; startEvents: click; from: 0.1 0.1 0.1; to: 1 1 1; dur: 150"
          animation__fusing="property: fusing; startEvents: fusing; from: 1 1 1; to: 0.1 0.1 0.1; dur: 1500"
          event-set__mouseenter="_event: mouseenter; color: springgreen"
          event-set__mouseleave="_event: mouseleave; color: black"
          raycaster="objects: .link"></a-cursor> -->
      </a-entity>
    </a-scene>
  </body>
</html>

Exercise 7: Scene Switching

This example shows how we can switch between two scenes by dynamically loading a new scene.
https://supermedium.com/superframe/components/template/examples/swapping/

The code can be found here:

https://github.com/supermedium/superframe/tree/master/components/template/examples/swapping

<!DOCTYPE html>
<html>
  <head>
    <title>Swapping</title>
    <meta name="description" content="Swapping templates to change contents of placeholder entitiy"></meta>
    <meta property="og:image" content="https://raw.githubusercontent.com/supermedium/superframe/master/components/template/examples/swapping/preview.gif"></meta>
    <script src="../build.js"></script>
    <script src="components/template-looper.js"></script>
  </head>
  <body>
    <a-scene>
      <a-entity template="src: scenes/spheres.html"
                template-looper="scenes/boxes.html, scenes/spheres.html"
                position="0 0 -8"></a-entity>

      <a-sky color="#D7C1E0"></a-sky>

      <a-sky id="mask" color="#111" opacity="0" radius="2">
        <a-animation attribute="material.opacity" begin="fade" from="0" to="1" dur="200" direction="alternate" repeat="1"></a-animation>
      </a-sky>
    </a-scene>
  </body>
</html>

Exercise 8: Networked A-Frame

https://glitch.com/edit/#!/networked-aframe?path=public/index.html:1:0

Try out the example: https://networked-aframe.glitch.me/

<html>
  <head>
    <meta charset="utf-8">
    <title>Basic Example — Networked-Aframe</title>
    <meta name="description" content="Basic Example — Networked-Aframe">

    <script src="https://aframe.io/releases/0.9.0/aframe.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.4.5/socket.io.min.js"></script>
    <script src="easyrtc/easyrtc.js"></script>
    <script src="https://unpkg.com/networked-aframe@^0.6.0/dist/networked-aframe.min.js"></script>

    <script src="https://unpkg.com/aframe-randomizer-components@^3.0.1/dist/aframe-randomizer-components.min.js"></script>
    <script src="https://unpkg.com/aframe-particle-system-component@1.0.5/dist/aframe-particle-system-component.min.js"></script>
    <script src="/js/spawn-in-circle.component.js"></script>
  </head>
  <body>
    <a-scene networked-scene="
      room: basic;
      debug: true;
    ">
      <a-assets>

        <img id="grid" src="https://img.gs/bbdkhfbzkk/stretch/https://i.imgur.com/25P1geh.png" crossorigin="anonymous">
        <img id="sky" src="https://img.gs/bbdkhfbzkk/2048x2048,stretch/http://i.imgur.com/WqlqEkq.jpg" crossorigin="anonymous" />

        <!-- Templates -->

        <!-- Avatar -->
        <template id="avatar-template">
          <a-entity class="avatar">
            <a-sphere class="head"
              color="#5985ff"
              scale="0.45 0.5 0.4"
              random-color
            ></a-sphere>
            <a-entity class="face"
              position="0 0.05 0"
            >
              <a-sphere class="eye"
                color="#efefef"
                position="0.16 0.1 -0.35"
                scale="0.12 0.12 0.12"
              >
                <a-sphere class="pupil"
                  color="#000"
                  position="0 0 -1"
                  scale="0.2 0.2 0.2"
                ></a-sphere>
              </a-sphere>
              <a-sphere class="eye"
                color="#efefef"
                position="-0.16 0.1 -0.35"
                scale="0.12 0.12 0.12"
              >
                <a-sphere class="pupil"
                  color="#000"
                  position="0 0 -1"
                  scale="0.2 0.2 0.2"
                ></a-sphere>
              </a-sphere>
            </a-entity>
          </a-entity>
        </template>

        <!-- /Templates -->
      </a-assets>

      <a-entity id="player"
                camera
                networked="template:#avatar-template;attachTemplateToLocal:false;"
                position="0 1.6 0"
                spawn-in-circle="radius:3"
                wasd-controls
                look-controls>
        <a-sphere class="head"
          visible="false"
          random-color
        ></a-sphere>
      </a-entity>

      <a-entity position="0 0 0"
        geometry="primitive: plane; width: 10000; height: 10000;" rotation="-90 0 0"
        material="src: #grid; repeat: 10000 10000; transparent: true; metalness:0.6; roughness: 0.4; sphericalEnvMap: #sky;"></a-entity>

      <a-entity light="color: #ccccff; intensity: 1; type: ambient;" visible=""></a-entity>
      <a-entity light="color: #ffaaff; intensity: 1.5" position="5 5 5"></a-entity>

      <a-sky src="#sky" rotation="0 -90 0"></a-sky>
      <a-entity id="particles" particle-system="preset: snow"></a-entity>
    </a-scene>

    <script>
      // On mobile remove elements that are resource heavy
      var isMobile = AFRAME.utils.device.isMobile();

      if (isMobile) {
        var particles = document.getElementById('particles');
        particles.parentNode.removeChild(particles);
      }
      
      // Define custom schema for syncing avatar color, set by random-color
      NAF.schemas.add({
        template: '#avatar-template',
        components: [
          'position',
          'rotation',
          {
            selector: '.head',
            component: 'material',
            property: 'color'
          }
        ]
      });
    </script>
  </body>
</html>