Appearance
Dynamics.applyOrbit()
Spins elements around a center point using either fixed circles or realistic gravity physics.
1. Kinematic Orbit (Rigid)
If you give it a radius, the elements are locked to a perfect circle (or oval) around the center. They will smoothly follow the center point, and you can use bounds to keep them trapped inside a container.
The elements follow the cursor but stop at the container boundaries.
js
import { Dynamics } from 'animx/dynamics'
// Selecting multiple elements automatically spreads them evenly
Dynamics.applyOrbit('.moon', {
center: 'pointer',
radius: 80, // Activates Kinematic Mode
speed: 2, // Radians per second
trackingLerp: 0.1, // Follow the cursor
bounds: '.container' // Automatically pads bounds based on the orbit radius
});2. Newtonian Orbit (Physics)
If you skip the radius and provide gravity instead, AnimX turns on real physics! It automatically calculates how far away your elements are from the center and injects the perfect amount of speed to create a stable, circular orbit.
If you have multiple elements, they act just like a real solar system—planets closer to the sun will naturally orbit much faster than planets far away.
Earth Years: 0
Sun
Mercury
Venus
Earth
Mars
Jupiter
Saturn
Uranus
Neptune
js
const sun = document.querySelector('.sun');
const planets = document.querySelectorAll('.planet');
const panel = document.querySelector('.solar-panel');
let earthPrevAngle = null;
let earthYears = 0;
Dynamics.applyOrbit(planets, {
center: sun,
gravity: 1200000,
autoRotate: false,
onUpdate: ({ states }) => {
// Earth is the 3rd planet in the DOM array (index 2)
const earthState = states[2];
// Calculate Earth's live angle relative to the sun
const currentAngle = Math.atan2(earthState.y, earthState.x);
// When Earth crosses the right-side horizontal axis, one full orbit is completed!
if (earthPrevAngle !== null && earthState.x > 0 && earthPrevAngle < 0 && currentAngle >= 0) {
earthYears++;
panel.innerHTML = `Earth Years: ${earthYears}`;
}
earthPrevAngle = currentAngle;
}
});3. Elliptical Orbits (Kinematic)
You don't have to stick to perfect circles! By giving it a radiusX and radiusY, you can easily create ovals and elliptical orbits.
The element follows the defined elliptical path.
js
// The dashed path element tracks the pointer using a zero-radius orbit
Dynamics.applyOrbit('.o-path', {
center: 'pointer',
radius: 0,
autoRotate: false
});
Dynamics.applyOrbit('.comet', {
center: 'pointer',
radiusX: 180, // Horizontal radius
radiusY: 40, // Vertical radius
speed: 3
});4. Orbital Decay (Physics)
If you add a little bit of friction, the elements will slowly lose their speed over time. This causes their orbits to decay, spiraling beautifully into the center.
The orbiting elements experience friction and spiral into the center.
js
// The black hole element follows the pointer (faster)
Dynamics.applyFollower('.blackhole', {
leader: 'pointer',
stiffness: 250,
damping: 20
});
// The elements orbit the black hole element.
// Tighter orbit, faster speed
Dynamics.applyOrbit('.comet', {
center: '.blackhole',
gravity: 800000,
friction: 0.98
});5. Gravitational Softening
When an object gets too close to the center of gravity, it can get slingshotted away at insane speeds. The softening property smooths this out so it passes through the center gracefully.
A high softening value allows elements to float gently through the center, while a very low softening value preserves the massive gravitational slingshot effect.
The lower softening value causes the red element to experience a gravitational slingshot.
js
// High softening (graceful pass)
Dynamics.applyOrbit('.soft-comet', {
center: '.blackhole',
gravity: 1200000,
softening: 40,
friction: 0.98
});
// Low softening (gravitational slingshot)
Dynamics.applyOrbit('.stiff-comet', {
center: '.blackhole',
gravity: 1200000,
softening: 5,
friction: 0.98
});6. Callbacks
Orbits don't have a set duration—they run forever! Because of this, AnimX gives you an onUpdate callback that fires every single frame. This is perfect for updating numbers on the screen or drawing trails.
The onUpdate function gives you the exact live coordinates of the center point (targetX and targetY), plus a states array containing the live speed and position of every orbiting element.
Move your cursor and watch the live telemetry update as the orbit decays.
js
const panel = document.querySelector('.debug-panel');
// Visual representation of the spacetime gravity well tracking the mouse
Dynamics.applyOrbit('.gravity-well', {
center: 'pointer',
radius: 0,
autoRotate: false
});
Dynamics.applyOrbit('.comet-data', {
center: 'pointer',
gravity: 1500000,
friction: 0.985,
onUpdate: ({ states, targetX, targetY }) => {
const s = states[0];
// Calculate distance to the center
const dx = targetX - (s.layoutX + s.x);
const dy = targetY - (s.layoutY + s.y);
const dist = Math.round(Math.sqrt(dx * dx + dy * dy));
// Calculate velocity magnitude
const speed = Math.sqrt(s.vx * s.vx + s.vy * s.vy).toFixed(1);
// Update the UI panel
panel.innerHTML = \`
<div style="color:#10b981;font-weight:bold;margin-bottom:4px;">ORBIT TELEMETRY</div>
<div>Distance: \${dist}px</div>
<div>Velocity: \${speed} px/f</div>
\`;
}
});Properties
| Option | Type | Default | Description |
|---|---|---|---|
center | string | Element | {x, y} | null | The gravitational anchor point. Accepts 'pointer', a DOM element, or a coordinate object. |
mode | string | 'physics' | Automatically switches to 'kinematic' if radius is provided. |
bounds | string | Element | null | Clamps the pointer tracking anchor inside an element or 'container'. |
radius | number | - | Activates kinematic mode. The exact radial distance from the anchor. |
speed | number | 1 | (Kinematic Mode) Angular velocity in radians per second. |
gravity | number | 500000 | (Physics Mode) The gravitational constant ($G \cdot M$). |
softening | number | 30 | (Physics Mode) Prevents gravitational singularities (slingshots) when elements get too close to the center. |
friction | number | 1.0 | (Physics Mode) Velocity multiplier per frame. E.g. 0.99 decays the orbit. |
autoRotate | boolean | true | If true, automatically rotates the element to face its velocity vector (heading). |
autoOrbit | boolean | true | (Physics Mode) If true, automatically calculates and applies the exact tangential velocity needed for a stable circular orbit on the first frame. |
onUpdate Payload
The onUpdate callback receives a single payload object with the following properties:
| Property | Type | Description |
|---|---|---|
targetX | number | The live X coordinate of the gravitational center point. |
targetY | number | The live Y coordinate of the gravitational center point. |
states | Array | An array of physical state objects for every element in the orbit. |
State Object Properties
Each item in the states array tracks the live properties of a single orbiting element:
| Property | Type | Description |
|---|---|---|
el | HTMLElement | The raw DOM element being animated. |
x | number | The current horizontal translation (pixels). |
y | number | The current vertical translation (pixels). |
vx | number | Current X velocity in pixels per frame (Physics Mode only). |
vy | number | Current Y velocity in pixels per frame (Physics Mode only). |
angle | number | Current orbital phase in radians (Kinematic Mode only). |
layoutX | number | The original starting point (X coordinate) of the element before animation. |
layoutY | number | The original starting point (Y coordinate) of the element before animation. |