Skip to content

Commit

Permalink
Merge branch 'main' into patch-3
Browse files Browse the repository at this point in the history
  • Loading branch information
liuxuelian authored Nov 15, 2024
2 parents d8e5be5 + 4319d57 commit 0066490
Show file tree
Hide file tree
Showing 4 changed files with 627 additions and 176 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,45 @@ page-type: guide

{{GamesSidebar}}

The [WebXR](/en-US/docs/Games/Techniques/3D_on_the_web/WebXR) and [WebGL](/en-US/docs/Web/API/WebGL_API) APIs already enable us to start creating virtual reality (VR) and augmented reality (AR) experiences inside web browsers, but the community is still waiting for tools and libraries to appear, to make this easier. Mozilla's [A-Frame](https://aframe.io/) framework provides a markup language allowing us to build 3D VR landscapes using a system familiar to web developers, which follows game development coding principles; this is useful for quickly and successfully building prototypes and demos, without having to write a lot of JavaScript or GLSL. This article explains how to get up and running with A-Frame, and how to use it to build up a simple demo.
The [WebXR](/en-US/docs/Games/Techniques/3D_on_the_web/WebXR) and [WebGL](/en-US/docs/Web/API/WebGL_API) APIs already enable us to start creating virtual reality (VR) and augmented reality (AR) experiences inside web browsers.
To make this easier, Mozilla's [A-Frame](https://aframe.io/) framework provides a markup language that allows web developers to build 3D VR landscapes using a familiar approach, and which follows game development coding principles.
This is useful for quickly and successfully building prototypes and demos, without having to write a lot of JavaScript or GLSL.
This article explains how to get up and running with A-Frame, and how to use it to build up a simple demo.

> [!NOTE]
> This guide was last updated in November 2024, and is compatible with A-Frame version `1.6.0`.
## High level overview

A-Frame runs on most environments, such as desktop, mobile (iOS and Android), and devices such as Oculus Rift, Gear VR and HTC Vive.

A-Frame is built on top of [WebGL](/en-US/docs/Web/API/WebGL_API), and provides pre-built components to use in applications — models, video players, skyboxes, geometries, controls, animations, cursors, etc. It is based on the [entity component system](https://en.wikipedia.org/wiki/Entity_component_system), which is known in the game development world, but it targets web developers with a familiar markup structure, manipulable with JavaScript. The end result is 3D web experiences, which are VR-enabled by default.
A-Frame is built on top of [WebGL](/en-US/docs/Web/API/WebGL_API), and provides pre-built components to use in applications — models, video players, skyboxes, geometries, controls, animations, cursors, etc. It is based on the [entity component system](https://en.wikipedia.org/wiki/Entity_component_system), which is known in the game development world, but it targets web developers with a familiar markup structure that can be manipulated with JavaScript. The end result is 3D web experiences, which are VR-enabled by default.

## Development setup

To start developing with A-Frame, you should make sure you are using a modern browser with good [WebGL](/en-US/docs/Web/API/WebGL_API) support.
One option is to set up a VR device such as Oculus Rift or Google Cardboard for the experiments.

## Environment setup
If you're developing locally in an IDE, make a directory to store your experiments in and save a copy of the [latest A-Frame engine](https://aframe.io/docs/1.6.0/introduction/installation.html) inside that directory.
Alternatively, you can load A-Frame from a CDN:

Let's start by setting up an environment to create something with A-Frame. We'll then build up a demo and run it. You should start off by:
```html
<script src="https://aframe.io/releases/1.6.0/aframe.min.js"></script>
```

- Making sure you are using a modern browser with good WebGL support (and WebVR support if you have available VR hardware) such as the latest Firefox or Chrome — download [Firefox Nightly](https://www.mozilla.org/en-US/firefox/channel/desktop/) or Chrome (v54 or higher).
- (Optional) set up a VR device such as Oculus Rift or Google Cardboard.
- Create a new directory to store your project in.
- Save a copy of the latest [A-Frame JavaScript library file](https://github.com/aframevr/aframe/tree/master/dist) inside your directory (check the GitHub repository for latest stable a dev builds).
- Open the [A-Frame documentation](https://aframe.io/docs/) in a separate tab — it is useful to refer to.
Whichever way you choose to get started, make sure you have the [A-Frame documentation](https://aframe.io/docs/) open somewhere while you're working for reference.

## HTML structure
### HTML starter for A-Frame

The first step is to create an HTML document — inside your project directory, create a new `index.html` file, and save the follow HTML inside it:
If you're building your project locally in an IDE, here's the HTML structure to get started:

```html
<!doctype html>
<html lang="en-US">
<head>
<meta charset="utf-8" />
<title>MDN Games: A-Frame demo</title>
<script src="aframe.min.js"></script>
<script src="https://aframe.io/releases/1.6.0/aframe.min.js"></script>
</head>
<body>
<!-- HTML goes here -->
Expand All @@ -44,12 +54,10 @@ The first step is to create an HTML document — inside your project directory,

This contains some basic information like the document `charset` and {{htmlelement("title")}}. The {{htmlelement("script")}} element includes the A-Frame framework in the page; we will write our example code inside the {{htmlelement("body")}} element.

### Initializing the scene
### Initializing a scene in A-Frame

A scene is the place where everything happens. When creating new objects in the demo, we will be adding them all to the scene to make them visible on the screen. In A-Frame, the scene is represented by a [Scene entity](https://aframe.io/docs/core/scene.html).

> [!NOTE]
> An Entity is any element — it can be an object like a box, cylinder or cone, but it can also be a camera, light or sound source.
An Entity is any element — it can be an object like a box, cylinder or cone, but it can also be a camera, light or sound source.

Let's create the scene by adding an `<a-scene>` element inside the `<body>` element:

Expand All @@ -62,13 +70,11 @@ Let's create the scene by adding an `<a-scene>` element inside the `<body>` elem
Adding the cube to the scene is done by adding a simple [`<a-box>`](https://aframe.io/docs/primitives/a-box.html) element inside the `<a-scene>` element. Add it now:

```html
<a-box color="#0095DD" position="0 1 0" rotation="20 40 0"></a-box>
<a-box position="0.5 0.5 -3" rotation="0 10 0" color="#4CC3D9"></a-box>
```

It contains a few parameters already defined: `color`, `position` and `rotation` — these are fairly obvious, and define the base color of the cube, the position inside the 3D scene, and the rotation of the cube.

> [!NOTE]
> The distance values (e.g. for the cube y position) are unitless, and can basically be anything you deem suitable for your scene — millimeters, meters, feet, or miles — it's up to you.
The distance values (e.g. for the cube y position) are unitless, and can basically be anything you deem suitable for your scene — millimeters, meters, feet, or miles — it's up to you.

### Adding a background: Sky box

Expand All @@ -78,27 +84,40 @@ A sky box is a background for the 3D world, represented by an [`<a-sky>`](https:
<a-sky color="#DDDDDD"></a-sky>
```

At this point, if you save the code and refresh your browser you can already see the cube on the screen with our custom background:
## A-Frame shape example

![A 3D representation's illustration of a blue cube displayed on a lighter grey background.](cube.png)
At this point, if you save the code and refresh your browser you can already see the cube on the screen with our custom background:

Here's the code we have created so far:
```html live-sample___a-frame-intro
<script src="https://aframe.io/releases/1.6.0/aframe.min.js"></script>
<a-scene>
<a-sky color="#DDDDDD"></a-sky>
<a-box position="0.5 0.5 -3" rotation="0 10 0" color="#4CC3D9"></a-box>
</a-scene>
```

{{JSFiddleEmbed("https://jsfiddle.net/end3r/m85148b4/","","350")}}
```css hidden live-sample___a-frame-intro
body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
font-size: 0;
}
```

You can also [check it out on GitHub](https://github.com/end3r/MDN-Games-3D/blob/gh-pages/A-Frame/cube.html).
{{embedlivesample("a-frame-intro", "", "400px")}}

A-Frame takes care of setting up everything you need:

- A default light source and camera are included, so the cube is visible.
- The controls are already working: you can use the mouse for looking around and the keyboard for movement
(try the <kbd>W</kbd>, <kbd>A</kbd>, <kbd>S</kbd>, and <kbd>D</kbd> keys).

- There's even an "Enter VR mode" button in the bottom right corner of the screen, to allow you to shift to full screen, stereoscopic image viewing if you have the necessary VR hardware set up and ready.
- The controls are already working: you can use the mouse for looking around and the keyboard for movement.
Try the <kbd>W</kbd>, <kbd>A</kbd>, <kbd>S</kbd>, and <kbd>D</kbd> keys).
- There's an "Enter VR mode" button in the bottom right corner of the screen, to allow you to shift to full screen, stereoscopic image viewing if you have the necessary VR hardware set up and ready.

### Specifying a camera

A camera entity can be created by adding an [`<a-camera>`](https://aframe.io/docs/primitives/a-camera.html) element to the scene. We can set the position of the camera explicitly and move it back a little bit from the center of the scene, so we'll be able to see the shapes. Add this just before the closing `</a-scene>` element:
A camera entity can be created by adding an [`<a-camera>`](https://aframe.io/docs/primitives/a-camera.html) element to the scene. We can set the position of the camera explicitly and move it back a little bit from the center of the scene, so we'll be able to see the shapes. Add this just before the closing `</a-scene>` tag:

```html
<a-camera
Expand Down Expand Up @@ -178,10 +197,7 @@ cylinder.setAttribute("position", "3 1 0");
scene.appendChild(cylinder);
```

We're getting a reference to the scene handler first, then we create the cylinder element as an A-Frame entity. After that it's all about setting the proper attributes: `color`, `height`, `radius` and `position`. The last line adds the newly created cylinder to the scene. That's it — you've created three different shapes with A-Frame! Here's how it looks right now:

![An illustration of 3D representation of three different geometry shapes displayed on a grey background: the first one is a darker grey torus, the second is a blue cube and the last one is a yellow cylinder.](shapes.png)

We're getting a reference to the scene handler first, then we create the cylinder element as an A-Frame entity. After that it's all about setting the proper attributes: `color`, `height`, `radius` and `position`. The last line adds the newly created cylinder to the scene. That's it — you've created three different shapes with A-Frame!
It is impressive to be able to create such a scene with just a few lines of HTML and JavaScript.

## Animation
Expand Down Expand Up @@ -209,18 +225,11 @@ We can also add animation to entities with custom geometry like the torus, in mu

```html
<a-entity
geometry="
primitive: torus;
radius: 1;
radiusTubular: 0.1;
segmentsTubular: 12;"
material="
color: #EAEFF2;
roughness: 0.1;
metalness: 0.5;"
geometry="primitive: torus; radius: 1; radiusTubular: 0.1; segmentsTubular: 12;"
material="color: #EAEFF2; roughness: 0.1; metalness: 0.5;"
rotation="10 0 0"
position="-3 1 0"
animation="property: scale; to: 1 0.5 1; dir: alternate; dur: 2000; loop: true; easing: linear;">
animation="property: scale; to: 1 0.5 1; direction: alternate; dur: 2000; loop: true; easing: linear;">
</a-entity>
```

Expand All @@ -242,18 +251,77 @@ render();

We're using the `render()` function to update the cylinder's position on every frame. Try changing the given values on the `y` axis and see how it affects the movement.

## Conclusion
## A-Frame example with animation

Everything is rendered properly and animating — congratulations on building your first A-Frame scene! Here's how the final version looks and works:

{{JSFiddleEmbed("https://jsfiddle.net/lowperry/xmo62ku0/5/","","350")}}
```html live-sample___a-frame-animation
<script src="https://aframe.io/releases/1.6.0/aframe.min.js"></script>
<a-scene>
<a-sky color="#DDDDDD"></a-sky>

<a-light
type="directional"
color="#FFF"
intensity="0.5"
position="-1 1 2"></a-light>
<a-light type="ambient" color="#FFF"></a-light>

<a-camera position="0 1 4">
<a-cursor color="#0095DD" opacity="0.5" scale="2 2 2"> </a-cursor>
</a-camera>

<a-box
color="#0095DD"
rotation="20 40 0"
position="0 1 0"
animation="property: rotation; from: 20 0 0; to: 20 360 0;
dir: alternate; loop: true; dur: 4000; easing: easeInOutQuad;">
</a-box>

<a-entity
geometry="primitive: torus; radius: 1; radiusTubular: 0.1; segmentsTubular: 12;"
material="color: #EAEFF2; roughness: 0.1; metalness: 0.5;"
rotation="10 0 0"
position="-3 1 0"
animation="property: scale; to: 1 0.5 1; direction: alternate;
dur: 2000; loop: true; easing: linear;">
</a-entity>
</a-scene>

<script>
const scene = document.querySelector("a-scene");
const cylinder = document.createElement("a-cylinder");
cylinder.setAttribute("color", "#FF9500");
cylinder.setAttribute("height", "2");
cylinder.setAttribute("radius", "0.75");
cylinder.setAttribute("position", "3 1 0");
scene.appendChild(cylinder);
let t = 0;
function render() {
t += 0.01;
requestAnimationFrame(render);
cylinder.setAttribute("position", "3 " + (Math.sin(t * 2) + 1) + " 0");
}
render();
</script>
```

```css hidden live-sample___a-frame-animation
body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
font-size: 0;
}
```

If you have a VR device available, now is a good time to try out your scene with it too.
{{embedlivesample("a-frame-animation", "", "400px")}}

> [!NOTE]
> You can also [check it out on GitHub](https://github.com/end3r/MDN-Games-3D/blob/gh-pages/A-Frame/shapes.html).
## Summary

That was easier than you thought, right? A-Frame targets web developers by offering easy to use web markup and all the advantages that brings, such as JavaScript manipulation. It is easy to start with, but also provides a powerful API for advanced concepts, as well as dealing with cross browser differences and suchlike. The community is growing, just like the number of supported VR devices — it's a great time to start experimenting with such frameworks.
A-Frame targets web developers by offering easy to use web markup and all the advantages that brings, such as JavaScript manipulation. It is easy to start with, but also provides a powerful API for advanced concepts, as well as dealing with cross browser differences. It's a great time to start experimenting with such frameworks.

## See also

Expand Down
Loading

0 comments on commit 0066490

Please sign in to comment.