Appearance
Dynamics.applyCollision()
Turn your DOM elements into physical objects that bounce off each other and the walls of their container! applyCollision() uses circular hitboxes to calculate realistic 2D physics.
1. Container Billiards
To get started, simply pass an array of elements (or a CSS selector) to Dynamics.applyCollision(). AnimX will automatically track their positions and bounce them off one another.
Click the stage to scatter the balls with random velocity.
js
import { Dynamics } from 'animx/dynamics'
const engine = Dynamics.applyCollision('.balls', {
bounds: '#stage', // Container walls
friction: 0.995, // Rolling friction (1 = endless rolling)
restitution: 0.9 // Bounciness of collisions (1 = perfectly elastic)
});2. Collision & Wall Callbacks
You can listen for exactly when two items collide or when an item hits a wall by using the onCollide and onWallBounce callbacks. AnimX even provides the impact force of the collision, which is perfect for driving responsive UI animations (like making a ball squish harder the faster it hits the wall) or triggering sound effects.
Click the stage to see the balls squish when they collide.
js
Dynamics.applyCollision('.balls', {
bounds: '#stage',
onCollide: (el1, el2, impact) => {
console.log(`Collision between elements with impact force ${impact}`);
AnimX.animate(el1, { scale: 1.2, duration: 0.1, yoyo: true });
},
onWallBounce: (el, side, impact) => {
// side will be 'top', 'bottom', 'left', or 'right'
console.log(`Hit ${side} wall with force ${impact}`);
}
});3. Interactive Grab & Throw
Collisions play perfectly with the Interactable module! When dragging an element, use engine.setDragged(el, true) to temporarily pause physics on that specific element. When the user lets go, use engine.injectVelocity() to throw it back into the mix.
Drag and throw the white cue ball into the red targets!
js
const engine = Dynamics.applyCollision('.ball', { bounds: '#stage' });
let tracker;
Interactable.create('.cue-ball', {
bounds: '#stage',
onPress() {
// 1. Isolate the target from physics integration while interacting
engine.setDragged(this.target, true);
tracker = Dynamics.trackVelocity(this.target, 'x,y');
},
onRelease() {
// 2. Re-integrate the target upon release
engine.setDragged(this.target, false);
// 3. Inject the tracked pointer velocity
engine.injectVelocity(this.target, tracker.get('x'), tracker.get('y'));
tracker.kill();
}
});Properties & Methods
Configuration Options
| Option | Type | Default | Description |
|---|---|---|---|
friction | number | 0.99 | How much velocity the items retain per frame. 1.0 means they roll forever, while lower numbers (like 0.9) make them slow down quickly. |
restitution | number | 0.9 | The bounciness of the collision! 1.0 is perfectly bouncy (no energy lost), while 0.5 means it loses half its speed when bouncing. |
bounds | string | Element | { minX?: number, maxX?: number, minY?: number, maxY?: number } | null | The container walls. Accepts a CSS selector, DOM element, or custom coordinate object. |
onCollide | Function | null | Fires when two elements hit each other. Provides (el1, el2, impact), where impact is the force of the collision. |
onWallBounce | Function | null | Fires when an element hits the container wall. Provides (el, side, impact), where side is 'top', 'bottom', 'left', or 'right'. |
Engine Methods
The object returned by applyCollision() controls the entire simulation:
| Method | Description |
|---|---|
setDragged(el, true) | Tells the engine to ignore this element because the user is currently dragging it. |
setDragged(el, false) | Hands control of the element back to the physics engine. |
injectVelocity(el, vx, vy) | Instantly applies a push (velocity in px/s) to the element. Wakes up the engine automatically if it was sleeping. |
kill() | Stops the physics simulation completely and cleans up all listeners. |
state | Read-only array of all objects in the simulation, including their current x, y, vx, vy, and radius. |