Animating Entity Properties with A-Frame’s Built‑in Animation Component
Learn how to use A‑Frame’s animation component to animate numeric and color properties, see a working rotation example, and understand its limits and common pitfalls.
26 Jan 2026, 01:13 UTC

Quick answer
Use the animation component to smoothly transition any numeric or color property of an entity (position, rotation, scale, material color, etc.) over a set duration. The component handles the timing loop internally, so you only need to declare the start, end, duration, easing, and optional looping or keyframes in HTML.
How it works – a worked example
The following snippet makes a box rotate continuously around the Y‑axis:
<a-scene>
<a-box
id="spinningBox"
width="1" height="1" depth="1"
color="#4CC3D9"
animation__spin="property: rotation; to: 0 360 0; dur: 2000; loop: true; easing: linear"
>
</a-box>
</a-scene>
When the page loads, A‑Frame parses the string value of animation__spin:
- Property resolution – the string
property: rotationtells the component to target the entity’sobject3D.rotation(a THREE.Euler). - Target values –
to: 0 360 0is converted to radians internally; the component stores the start value (current rotation) and the end value. - Timing –
dur: 2000sets a 2‑second cycle;loop: truemakes it repeat. - Easing –
easing: linearselects a linear interpolation function; other built‑in easings (easeInQuad, easeOutCubic, etc.) are available. - Animation loop – the component registers a
requestAnimationFramecallback that, on each frame, computes the elapsed time, applies the easing function to the progress (0‑1), interpolates between start and end, and writes the result back to the target property.
Because the loop runs in the render step, the box appears to spin smoothly without any additional JavaScript.
Keyframe syntax
You can define explicit start and end values with from and to, or create multi‑step animations:
<a-entity
id="movingBox"
animation__move="property: position; from: 0 0 0; to: 0 5 0; dur: 1000; easing: easeInOutQuad"
animation__moveBack="property: position; from: 0 5 0; to: 0 0 0; dur: 1000; easing: easeInOutQuad; delay: 1000"
>
</a-entity>
Here two separate animations (animation__move and animation__moveBack) are chained via the delay
Limits and common pitfalls
What can be animated
- Numeric scalars or vectors (position, rotation, scale, width, height, depth).
- Color strings that A‑Frame can parse (
#rgb,#rrggbb,rgb(), named colors). - Any property that resolves to a number or color via the entity’s
getAttribute/setAttributeAPI.
Complex objects such as meshes, materials, or custom shader uniforms cannot be animated directly; you would need to expose the uniform as an attribute or use a custom component.
Interaction with other components
If another component (e.g., a physics system) writes to the same property each frame, the animation component will overwrite those values, potentially causing jitter or unstable behavior. To avoid this, either:
- Animate a property that the other component does not touch (e.g., animate a wrapper entity’s position while physics drives the inner entity).
- Use the animation component’s
pauseOnBlurflag (if available in your A‑Frame version) to stop the loop when the page loses focus, reducing conflicts.
Performance considerations
Each active animation adds a callback to the render loop. On low‑end devices, many simultaneous long‑duration animations can drop frames. Profile with Chrome DevTools → Performance panel and watch the requestAnimationFrame time. If you see spikes, consider:
- Combining related animations into a single component with multiple keyframes.
- Using
durvalues that match the scene’s frame budget (e.g., 16 ms per frame for 60 fps). - Disabling animations when they are off‑screen or not needed.
Common mistakes
- String vs. number – Writing
to: "5"(quoted) can cause type‑coercion issues in A‑Frame 1.x; always use unquoted numbers for numeric properties. - Missing unit – Rotation values are interpreted as degrees; if you intend radians, convert them yourself before passing to the component.
- Overwriting – Declaring two animations with the same name (e.g., two
animation__spin) causes the later definition to replace the earlier one; use unique suffixes (animation__spin1,animation__spin2) for distinct tracks. - Assuming automatic pause – The animation component does not pause when the tab becomes hidden unless you set
pauseOnBlur: true(available in newer builds). Forgetting this can lead to unnecessary CPU usage.
Practical verification steps
To confirm that an animation is behaving as expected:
- Load the scene in a browser and open the A‑Frame Inspector (Ctrl+Shift+I or right‑click → Inspect).
- Select the animated entity; the Inspector panel lists all components, including
animation__*with the values you supplied. - In the console, run
document.querySelector('a-box').components.animation__spinand observe theisPlayingflag and thedataobject. - Manually change a property (e.g., set
entity.setAttribute('animation__spin', 'paused', true)) and verify that the motion stops. - For keyframe animations, watch the entity’s position/rotation over time and compare the perceived easing to the selected function (you can overlay a CSS transition of the same easing for a visual reference).
These steps let you verify that the component is active, that the target property updates each frame, and that you can control playback via the API.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.