Skip to main content
Harmonica is a port of charmbracelet/harmonica, a spring-physics library that produces natural-feeling animations. Instead of linear tweens, it simulates a damped spring that overshoots and settles, giving motion a physical weight. The Java package is com.williamcallahan.tui4j.compat.harmonica.

How it works

A Spring computes new position and velocity values each frame from the current state and a target equilibrium. Call update() once per frame and write the resulting position to your view:
The spring converges on target at a rate determined by three parameters: FPS, frequency, and damping.

Creating a spring

Spring.newSpring(double deltaTime, double angularFrequency, double dampingRatio)

Advancing the simulation

Call update(pos, vel, equilibriumPos) once per animation frame:
The method returns a two-element double[] array: [newPosition, newVelocity]. Store both values and feed them back into the next update() call.

Complete example: animated ellipse following the mouse

The cell-buffer example uses two independent springs — one for the X axis and one for the Y axis — to smoothly chase the mouse cursor:

Animating a progress bar

Use a single spring to animate a bar toward a target width:

Tuning the parameters

When angularFrequency is zero, newSpring returns a no-op spring that always returns the current position unchanged — useful for disabling animation without changing your update logic.
Harmonica springs are stateless value objects. The state (position and velocity) lives in your model, not in the Spring instance. You can safely share a single Spring across multiple animated values as long as each value has its own position and velocity fields.

Projectile motion

Projectile simulates ballistic motion under acceleration. It is useful for effects like particles or bouncing elements:

Mouse input

Combine mouse tracking with spring animation

External commands

Launch editors and shells from your TUI