Declare Entity Motion in A-Frame Without Writing Timers
Use A-Frame’s animation component to rotate, move, or scale entities with HTML attributes instead of custom JavaScript timers.
24 May 2026, 06:29 UTC

Problem: moving a VR object without imperative JavaScript
You need a cube to spin when a visitor clicks it, or a door to slide open when the scene loads. Writing a timer loop or an event listener that mutates object3D.position every frame works, but it scatters timing logic across JavaScript files and makes the scene harder to read.
Thesis: declare motion in markup
A-Frame’s animation component lets you describe motion directly on an entity using HTML attributes. You name the property to change, provide start and end values, and set a duration in milliseconds. A-Frame runs the tick loop and handles interpolation.
How the animation component works
The component lives on <a-entity> as an animation attribute. Its settings are separated by semicolons:
| Attribute | Purpose | Example |
|---|---|---|
property | Component or object3D property to animate | rotation |
from | Starting value | 0 0 0 |
to | Ending value | 360 0 0 |
dur | Duration in milliseconds, not seconds | 4000 |
easing | Interpolation curve, such as linear or easeInOutQuad | linear |
loop | Repeat the animation indefinitely | true |
startEvents | Space-separated events that trigger the animation | click |
If you omit startEvents, the animation starts when the scene loads. Supported properties include numeric vectors, colors, and any component attribute with a setter.
Worked example: rotating cube
Save the following as index.html. It loads A-Frame 1.5.0 from a CDN and spins a cube around its X axis.
<!DOCTYPE html>
<html>
<head>
<script src='https://cdn.jsdelivr.net/npm/aframe@1.5.0/dist/aframe.min.js'></script>
</head>
<body>
<a-scene>
<a-entity id='cube'
geometry='primitive: box'
position='0 1.5 -5'
material='color: #4CC3D9'
animation='property: rotation; from: 0 0 0; to: 360 0 0; dur: 4000; easing: linear; loop: true'>
</a-entity>
<a-entity camera position='0 1.6 0'></a-entity>
<a-entity light='type: ambient'></a-entity>
</a-scene>
</body>
</html>
Where to run it
Run this command in the folder that contains index.html:
python -m http.server 8000
No administrator permissions are required. Open http://localhost:8000 in a browser. Do not open the file directly with file://; A-Frame may block modules or textures under that protocol. The command serves the current directory over HTTP, so avoid running it in a folder that contains sensitive files.
Expected result
The cube completes one full turn every four seconds and repeats because loop is true.
Verify the animation
- Open browser DevTools and select the
#cubeelement. - Confirm the
animationattribute containsdur: 4000. - In the console, run:
document.querySelector('#cube').components.animation
You should see an object with properties such as from, to, and dur, which confirms the attribute was parsed. If the value is undefined, check that the A-Frame script loaded before your entity markup.
Limitations and trade-offs
One animation component interpolates between exactly two values. To move an object along a multi-point path, use several animations or custom JavaScript. A single entity cannot carry duplicate animation attributes in HTML; use namespaced names such as animation__spin and animation__float instead.
Easing is built in, but per-frame logic—for example, moving an entity toward a tracked controller—requires the A-Frame JavaScript API. Long animation strings also make HTML harder to maintain across many entities.
Closing checklist
- Serve the page over HTTP, not
file://. - Confirm the A-Frame script is version 1.5 or later.
- Remember that
duruses milliseconds. - Inspect
components.animationin DevTools to confirm parsing. - Test on the target headset; many animated entities can reduce frame rate.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.