Hand off release velocity
Start the spring at the release velocity so drag and settle are one.
From apple-design, §5, after Designing Fluid Interfaces ↗.
Throw the sheet
Flick a sheet and let go mid-motion, or press Throw both.
Starts at 0 px/sBad
spring({ from: y, to, velocity: 0 })Starts at releaseGood
spring({ from: y, to, velocity: v })sheet.addEventListener("pointerup", (e) => {
const v = releaseVelocity(history, e.timeStamp);
spring({ from: y, to, velocity: v, onUpdate: render });
});
Measure the release velocity
Drag the knob and release while moving, then while still.
From pointer historyLive
- Last event only
- 0 px/s
- Windowed
- 0 px/s
- Target − current
- 0 px
- Relative velocity
- 0
v = Δp / Δt over the last windowconst recent = history.filter((s) => now - s.t <= 100);
if (recent.length < 2) return 0;
Match the API's velocity units
Edit the values, then press Play.
relativeVelocity = 50 / (150 − 50) = 0.5
Raw px/s as relativeBad
initialSpringVelocity: 50Normalized by distanceGood
initialSpringVelocity: 0.5animate(el, { y: 150 }, { type: "spring", velocity: 50 });
const relative = 50 / (150 - 50);
Why it matters, pros and cons
Why it matters
Starting at zero drops the speed for a frame. The eye reads that dip as a seam.
Pros
- Drag and settle read as one motion.
- Harder throws land with more energy.
- Same number picks the snap target.
Cons
- Last-event velocity is noisy; average over 100 ms.
- A finger held still must yield zero.
- Raw px/s into relative APIs overshoots wildly.