Skip to content

Dynamics.applyFluidDrag()

Simulate elements falling, floating, or flying through the air, water, or even thick syrup! applyFluidDrag() calculates realistic air resistance (drag) so that falling items naturally hit Terminal Velocity and don't accelerate forever.


1. High Drag Drop

Watch how a high drag value simulates dropping a ball into a thick fluid. It accelerates at first, but quickly hits its speed limit!

Click the stage to drop the ball.
60 FPS
js
import { Dynamics } from 'animx/dynamics'

Dynamics.applyFluidDrag('.ball', {
  gravity: 1200,    // Downward acceleration (px/s²)
  drag: 0.005,      // Fluid thickness (higher = thicker syrup)
  bounce: 0.5,      // Energy retained after hitting walls (0-1)
  bounds: '#stage'  // Container element for walls/floor calculation
})

2. Terminal Velocity Comparison

By tweaking the drag value, you can easily simulate different physical mediums. Notice how the syrup ball barely bounces because the fluid is so thick!

Click the stage to drop all three balls.
Air
Water
Syrup
60 FPS
js
// Air (bounces high)
Dynamics.applyFluidDrag('.air', { gravity: 1500, drag: 0.0001, bounce: 0.8 });

// Water
Dynamics.applyFluidDrag('.water', { gravity: 1500, drag: 0.002, bounce: 0.4 });

// Thick Syrup (barely bounces)
Dynamics.applyFluidDrag('.syrup', { gravity: 1500, drag: 0.02, bounce: 0.1 });

3. Horizontal Splash (Initial Velocity)

Because drag scales with speed, if you throw something really fast, the air resistance slows it down incredibly quickly. Perfect for splashes or explosions!

Click the stage to fire the ball horizontally.
60 FPS
js
Dynamics.applyFluidDrag('.splash', {
  gravity: 800,
  drag: 0.008,
  initialVelocityX: 3000, // Massive initial speed
  initialVelocityY: -200, // Slight upward arc
  bounce: 0.4,
  bounds: '#stage'
});

4. Feather vs. Cannonball (Mass)

Heavy items punch right through the air, while lighter items get caught in it! By setting the mass property, you can easily replicate the classic feather vs. cannonball experiment.

Drop the items in air, then toggle the vacuum to see them drop together!
Feather
10kg
60 FPS
js
// Use a toggle to switch between air (drag: 0.005) and vacuum (drag: 0)
const drag = isVacuum ? 0 : 0.005;

// Feather (mass 0.5) gets slowed down heavily by air drag, but falls at 1g in vacuum
Dynamics.applyFluidDrag('.feather', { gravity: 1200, drag, mass: 0.5 });

// Cannonball (mass 10) punches right through the drag either way
Dynamics.applyFluidDrag('.cannonball', { gravity: 1200, drag, mass: 10 });

5. Underwater Bubbles (Negative Gravity)

You can use negative gravity values to make things float upwards instead of falling down! When combined with a little drag, it creates a perfect underwater bubble effect.

Click to release the bubbles!
60 FPS
js
// Gravity points UP (-1500), but drag stops them from flying too fast!
const engine = Dynamics.applyFluidDrag('.bubbles', {
  gravity: -1500,
  drag: 0.015,
  bounce: 0.3,
  bounds: '#stage'
});

// Add some random horizontal scatter to make them drift slightly
document.querySelectorAll('.bubbles').forEach(bubble => {
  engine.injectVelocity(bubble, (Math.random() - 0.5) * 800, 0);
});

Properties & Methods

Configuration Options

OptionTypeDefaultDescription
gravitynumber980Downward pull in px/s². Use negative numbers to make things float up!
dragnumber0.002How thick the fluid is. Higher numbers (like 0.02) simulate thick syrup, while low numbers simulate thin air.
massnumber1The weight of the item. Heavier items ignore drag more easily.
bouncenumber0.5How bouncy the item is when it hits the bounds (0 is a dead stop, 1 is perfectly bouncy).
boundsstring | Element | { minX?: number, maxX?: number, minY?: number, maxY?: number }nullThe container element or custom limits so items know where the floor and walls are.
initialVelocityXnumber0Give the item an instant horizontal push when the engine starts (px/s).
initialVelocityYnumber0Give the item an instant vertical push when the engine starts (px/s).

Engine Methods

The object returned by applyFluidDrag() lets you interact with the running simulation:

MethodDescription
kill()Stops the physics engine immediately and cleans up.
injectVelocity(el, vx, vy)Instantly applies a push (velocity in px/s) to the element while it's running.