Skip to content

Reduce filesize of spring and inertia generators - #3799

Open
mattgperry wants to merge 1 commit into
mainfrom
generator-filesize-optimisations
Open

Reduce filesize of spring and inertia generators#3799
mattgperry wants to merge 1 commit into
mainfrom
generator-filesize-optimisations

Conversation

@mattgperry

Copy link
Copy Markdown
Collaborator

Summary

Filesize pass over the spring and inertia generators: -374 bytes minified / -107 bytes gzipped (4,773 → 4,399 min, 2,185 → 2,078 gzip, measured by bundling spring + inertia + pregenerateKeyframes with esbuild).

  • spring: The underdamped position/velocity math existed in three places (resolveSpring, resolveVelocity, and an inlined copy in the next() hot path). It now exists once, in a sample(t) closure memoized by t that computes both values while sharing the exp/sin/cos terms — same one-trig-evaluation-per-frame behavior, single-path next(). Also hoists the repeated dampingRatio * undampedAngularFreq product and replaces Math.pow(x, 2) with multiplication in findSpring. Output is bit-identical (spring tests pass unchanged).
  • inertia: applyFriction calculates calcDelta once per frame instead of twice. The boundary spring now receives the exact analytical derivative of the friction curve (-calcDelta(t) / timeConstant per ms) instead of a 5ms finite-difference sample, removing calcLatest and the getGeneratorVelocity import and resolving the stale units TODO on that line. isOutOfBounds relies on comparisons against undefined always being false.
  • generators/utils: calcGeneratorDuration now accepts optional timeStep, maxDuration and keyframes parameters so pregenerateKeyframes reuses the same sampling loop instead of duplicating it.

Behaviour notes

  • The analytical inertia boundary velocity shifts bounce trajectories by at most 0.033 units on the 200-unit test animation (~0.016%), only after the boundary crossing; durations unchanged. The pinned keyframe expectations in inertia.test.ts were regenerated and verified programmatically (values before the boundary are bit-identical, min/max cases deviate symmetrically).
  • A generator that never rests now caps pregeneration at exactly 10,000ms (one extra keyframe) instead of 9,990ms.

Test plan

  • motion-dom Jest suite (67 suites, 509 tests)
  • framer-motion client Jest suite (97 suites, 815 tests)
  • ESLint clean on changed files

Made with Cursor

- Dedupe the underdamped spring position/velocity math into a single
  memoized sampler shared by resolveSpring, resolveVelocity and the
  next() hot path
- Hoist repeated dampingRatio * undampedAngularFreq product and replace
  Math.pow(x, 2) with multiplication in findSpring
- Use the analytical derivative of the inertia friction curve for the
  boundary spring velocity instead of finite-difference sampling
- Calculate delta once per frame in applyFriction
- Unify calcGeneratorDuration and pregenerateKeyframes into one
  parametrized sampling loop

Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant