120 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			120 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| import { __rest } from 'tslib';
 | |
| import { findSpring, calcAngularFreq } from '../utils/find-spring.mjs';
 | |
| 
 | |
| const durationKeys = ["duration", "bounce"];
 | |
| const physicsKeys = ["stiffness", "damping", "mass"];
 | |
| function isSpringType(options, keys) {
 | |
|     return keys.some((key) => options[key] !== undefined);
 | |
| }
 | |
| function getSpringOptions(options) {
 | |
|     let springOptions = Object.assign({ velocity: 0.0, stiffness: 100, damping: 10, mass: 1.0, isResolvedFromDuration: false }, options);
 | |
|     if (!isSpringType(options, physicsKeys) &&
 | |
|         isSpringType(options, durationKeys)) {
 | |
|         const derived = findSpring(options);
 | |
|         springOptions = Object.assign(Object.assign(Object.assign({}, springOptions), derived), { velocity: 0.0, mass: 1.0 });
 | |
|         springOptions.isResolvedFromDuration = true;
 | |
|     }
 | |
|     return springOptions;
 | |
| }
 | |
| function spring(_a) {
 | |
|     var { from = 0.0, to = 1.0, restSpeed = 2, restDelta } = _a, options = __rest(_a, ["from", "to", "restSpeed", "restDelta"]);
 | |
|     const state = { done: false, value: from };
 | |
|     let { stiffness, damping, mass, velocity, duration, isResolvedFromDuration, } = getSpringOptions(options);
 | |
|     let resolveSpring = zero;
 | |
|     let resolveVelocity = zero;
 | |
|     function createSpring() {
 | |
|         const initialVelocity = velocity ? -(velocity / 1000) : 0.0;
 | |
|         const initialDelta = to - from;
 | |
|         const dampingRatio = damping / (2 * Math.sqrt(stiffness * mass));
 | |
|         const undampedAngularFreq = Math.sqrt(stiffness / mass) / 1000;
 | |
|         if (restDelta === undefined) {
 | |
|             restDelta = Math.min(Math.abs(to - from) / 100, 0.4);
 | |
|         }
 | |
|         if (dampingRatio < 1) {
 | |
|             const angularFreq = calcAngularFreq(undampedAngularFreq, dampingRatio);
 | |
|             resolveSpring = (t) => {
 | |
|                 const envelope = Math.exp(-dampingRatio * undampedAngularFreq * t);
 | |
|                 return (to -
 | |
|                     envelope *
 | |
|                         (((initialVelocity +
 | |
|                             dampingRatio * undampedAngularFreq * initialDelta) /
 | |
|                             angularFreq) *
 | |
|                             Math.sin(angularFreq * t) +
 | |
|                             initialDelta * Math.cos(angularFreq * t)));
 | |
|             };
 | |
|             resolveVelocity = (t) => {
 | |
|                 const envelope = Math.exp(-dampingRatio * undampedAngularFreq * t);
 | |
|                 return (dampingRatio *
 | |
|                     undampedAngularFreq *
 | |
|                     envelope *
 | |
|                     ((Math.sin(angularFreq * t) *
 | |
|                         (initialVelocity +
 | |
|                             dampingRatio *
 | |
|                                 undampedAngularFreq *
 | |
|                                 initialDelta)) /
 | |
|                         angularFreq +
 | |
|                         initialDelta * Math.cos(angularFreq * t)) -
 | |
|                     envelope *
 | |
|                         (Math.cos(angularFreq * t) *
 | |
|                             (initialVelocity +
 | |
|                                 dampingRatio *
 | |
|                                     undampedAngularFreq *
 | |
|                                     initialDelta) -
 | |
|                             angularFreq *
 | |
|                                 initialDelta *
 | |
|                                 Math.sin(angularFreq * t)));
 | |
|             };
 | |
|         }
 | |
|         else if (dampingRatio === 1) {
 | |
|             resolveSpring = (t) => to -
 | |
|                 Math.exp(-undampedAngularFreq * t) *
 | |
|                     (initialDelta +
 | |
|                         (initialVelocity + undampedAngularFreq * initialDelta) *
 | |
|                             t);
 | |
|         }
 | |
|         else {
 | |
|             const dampedAngularFreq = undampedAngularFreq * Math.sqrt(dampingRatio * dampingRatio - 1);
 | |
|             resolveSpring = (t) => {
 | |
|                 const envelope = Math.exp(-dampingRatio * undampedAngularFreq * t);
 | |
|                 const freqForT = Math.min(dampedAngularFreq * t, 300);
 | |
|                 return (to -
 | |
|                     (envelope *
 | |
|                         ((initialVelocity +
 | |
|                             dampingRatio * undampedAngularFreq * initialDelta) *
 | |
|                             Math.sinh(freqForT) +
 | |
|                             dampedAngularFreq *
 | |
|                                 initialDelta *
 | |
|                                 Math.cosh(freqForT))) /
 | |
|                         dampedAngularFreq);
 | |
|             };
 | |
|         }
 | |
|     }
 | |
|     createSpring();
 | |
|     return {
 | |
|         next: (t) => {
 | |
|             const current = resolveSpring(t);
 | |
|             if (!isResolvedFromDuration) {
 | |
|                 const currentVelocity = resolveVelocity(t) * 1000;
 | |
|                 const isBelowVelocityThreshold = Math.abs(currentVelocity) <= restSpeed;
 | |
|                 const isBelowDisplacementThreshold = Math.abs(to - current) <= restDelta;
 | |
|                 state.done =
 | |
|                     isBelowVelocityThreshold && isBelowDisplacementThreshold;
 | |
|             }
 | |
|             else {
 | |
|                 state.done = t >= duration;
 | |
|             }
 | |
|             state.value = state.done ? to : current;
 | |
|             return state;
 | |
|         },
 | |
|         flipTarget: () => {
 | |
|             velocity = -velocity;
 | |
|             [from, to] = [to, from];
 | |
|             createSpring();
 | |
|         },
 | |
|     };
 | |
| }
 | |
| spring.needsInterpolation = (a, b) => typeof a === "string" || typeof b === "string";
 | |
| const zero = (_t) => 0;
 | |
| 
 | |
| export { spring };
 | 
