Skip to documentation
CranberryClock.Ideas / Systems / Design

INDEPENDENT TOOL / v0.1.0

SpringIntegration guide

Install Spring, connect it to your project, and understand the integration boundaries.

Start with the package archive.

Download Spring v0.1.0 ↓, then follow the installation instructions below. Commands that pack source files run from the public repository checkout.

Install

Download cranberry-forge-spring-0.1.0.tgz from the Spring page, then install the local archive:

bash
npm install ./cranberry-forge-spring-0.1.0.tgz

The archive is an ES module with TypeScript declarations. You can also copy index.js into your project and import that file directly. This repository does not imply that the package is published to the public npm registry.

javascript
import { Spring } from "@cranberry-forge/spring";

const recoil = new Spring({ frequency: 3, dampingRatio: 0.65 });

function onAction() {
  recoil.impulse(8); // velocity units per second
}

function update(dt) {
  mesh.position.y = restY + recoil.step(dt); // dt in seconds
}

What the two controls mean

frequency is the undamped natural frequency in hertz, not a duration. dampingRatio is dimensionless:

Ratio Motion
0 Undamped; oscillation continues.
Between 0 and 1 Underdamped; decaying oscillation.
1 Critical damping. A target change from rest approaches without overshoot.
Above 1 Overdamped; two decaying modes, without sustained oscillation.

An existing velocity can carry even a critically damped or overdamped spring across the target. Spring preserves that velocity. It does not silently clamp crossings or snap at a hidden rest threshold.

The implementation evaluates the closed-form solution of x″ + 2ζω x′ + ω²(x − target) = 0, with ω = 2π × frequency. These are the standard damped-oscillator regimes described in MIT OpenCourseWare’s damped harmonic oscillator lesson.

Guarantees and boundaries

  • For a constant target and unchanged settings, one step and several steps totaling the same time agree up to floating-point rounding. If target changes or impulses happen between steps, split at those event times for equivalent results.
  • Under-, critical-, and overdamping use analytic formulas. Near-critical damping uses stable sinc/expm1 forms; overdamping avoids overflowing sinh intermediates.
  • Scalar and XYZ operations validate finite inputs. Failed configuration, impulses, or numerical-limit checks preserve the previous state. XYZ stepping commits all three axes together.
  • Getters return detached data. The object supplied to the pure stepSpring function is not mutated.
  • Time steps are 0..60 seconds; frequency is 0.01..100 Hz; ratio is 0..10. Each scalar value, target, velocity, and impulse component must have magnitude at most 1e12. Computed states exceeding that limit throw rather than clip.
  • Spring owns no resources to dispose. Stop calling step to pause. Call snap() when your product wants reduced motion, and stop applying decorative impulses.

Read the API reference or follow the integration tutorial. The repository’s nine focused tests cover analytic reference values, energy, timestep equivalence, momentum, XYZ parity, resets, and atomic rejection.

Optional local HTTP endpoint

The Cranberry Forge repository server also exposes POST /api/v1/spring/step for explicit numeric requests:

json
{
  "state": { "value": 0, "target": 1, "velocity": 0 },
  "dt": 0.016,
  "options": { "frequency": 2, "dampingRatio": 0.65 }
}

It returns { "state": { "value": ..., "velocity": ..., "target": ... } }. This optional repository service is separate from the standalone package; ordinary animation should step locally in its own frame loop. See the repository’s HTTP API documentation.

Original implementation and Jellyworks procedural toys: MIT. No third-party animation code is bundled.

View versioned source on GitHub ↗