Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | 5x 5x 5x 5x 5x 9753x 9753x 9753x 9753x 9753x 9753x 9753x 9753x 9753x 9753x 214566x 214566x 214566x 214566x 214566x 214566x 9753x 107283x 107283x 107283x 107283x 107283x 107283x 107283x 107283x 9753x 9753x 9753x 9753x 9753x 5x 9753x 9753x 107283x 9753x 321870x | import { warning } from "hey-listen" import { clamp } from "../../utils/clamp" import { SpringOptions } from "../types" /** * This is ported from the Framer implementation of duration-based spring resolution. */ type Resolver = (num: number) => number const safeMin = 0.001 export const minDuration = 0.01 export const maxDuration = 10.0 export const minDamping = 0.05 export const maxDamping = 1 export function findSpring({ duration = 800, bounce = 0.25, velocity = 0, mass = 1, }: SpringOptions) { let envelope: Resolver let derivative: Resolver warning( duration <= maxDuration * 1000, "Spring duration must be 10 seconds or less" ) let dampingRatio = 1 - bounce /** * Restrict dampingRatio and duration to within acceptable ranges. */ dampingRatio = clamp(minDamping, maxDamping, dampingRatio) duration = clamp(minDuration, maxDuration, duration / 1000) Eif (dampingRatio < 1) { /** * Underdamped spring */ envelope = (undampedFreq) => { const exponentialDecay = undampedFreq * dampingRatio const delta = exponentialDecay * duration const a = exponentialDecay - velocity const b = calcAngularFreq(undampedFreq, dampingRatio) const c = Math.exp(-delta) return safeMin - (a / b) * c } derivative = (undampedFreq) => { const exponentialDecay = undampedFreq * dampingRatio const delta = exponentialDecay * duration const d = delta * velocity + velocity const e = Math.pow(dampingRatio, 2) * Math.pow(undampedFreq, 2) * duration const f = Math.exp(-delta) const g = calcAngularFreq(Math.pow(undampedFreq, 2), dampingRatio) const factor = -envelope(undampedFreq) + safeMin > 0 ? -1 : 1 return (factor * ((d - e) * f)) / g } } else { /** * Critically-damped spring */ envelope = (undampedFreq) => { const a = Math.exp(-undampedFreq * duration) const b = (undampedFreq - velocity) * duration + 1 return -safeMin + a * b } derivative = (undampedFreq) => { const a = Math.exp(-undampedFreq * duration) const b = (velocity - undampedFreq) * (duration * duration) return a * b } } const initialGuess = 5 / duration const undampedFreq = approximateRoot(envelope, derivative, initialGuess) Iif (isNaN(undampedFreq)) { return { stiffness: 100, damping: 10, } } else { const stiffness = Math.pow(undampedFreq, 2) * mass return { stiffness, damping: dampingRatio * 2 * Math.sqrt(mass * stiffness), } } } const rootIterations = 12 function approximateRoot( envelope: Resolver, derivative: Resolver, initialGuess: number ): number { let result = initialGuess for (let i = 1; i < rootIterations; i++) { result = result - envelope(result) / derivative(result) } return result } export function calcAngularFreq(undampedFreq: number, dampingRatio: number) { return undampedFreq * Math.sqrt(1 - dampingRatio * dampingRatio) } |