UNPKG

photoswipe

Version:
76 lines (63 loc) 1.91 kB
import SpringEaser from './spring-easer.js'; /** @typedef {import('./animations.js').SharedAnimationProps} SharedAnimationProps */ /** * @typedef {Object} DefaultSpringAnimationProps * * @prop {number} start * @prop {number} end * @prop {number} velocity * @prop {number} [dampingRatio] * @prop {number} [naturalFrequency] * @prop {(end: number) => void} onUpdate */ /** @typedef {SharedAnimationProps & DefaultSpringAnimationProps} SpringAnimationProps */ class SpringAnimation { /** * @param {SpringAnimationProps} props */ constructor(props) { this.props = props; this._raf = 0; const { start, end, velocity, onUpdate, onComplete, onFinish = () => {}, dampingRatio, naturalFrequency } = props; this.onFinish = onFinish; const easer = new SpringEaser(velocity, dampingRatio, naturalFrequency); let prevTime = Date.now(); let deltaPosition = start - end; const animationLoop = () => { if (this._raf) { deltaPosition = easer.easeFrame(deltaPosition, Date.now() - prevTime); // Stop the animation if velocity is low and position is close to end if (Math.abs(deltaPosition) < 1 && Math.abs(easer.velocity) < 50) { // Finalize the animation onUpdate(end); if (onComplete) { onComplete(); } this.onFinish(); } else { prevTime = Date.now(); onUpdate(deltaPosition + end); this._raf = requestAnimationFrame(animationLoop); } } }; this._raf = requestAnimationFrame(animationLoop); } // Destroy is called automatically onFinish destroy() { if (this._raf >= 0) { cancelAnimationFrame(this._raf); } this._raf = 0; } } export default SpringAnimation;