import { easeInOut } from '../../easing/ease.mjs'; import { isEasingArray } from '../../easing/utils/is-easing-array.mjs'; import { easingDefinitionToFunction } from '../../easing/utils/map.mjs'; import { interpolate } from '../../utils/interpolate.mjs'; import { defaultOffset } from '../../utils/offsets/default.mjs'; import { convertOffsetToTimes } from '../../utils/offsets/time.mjs'; function defaultEasing(values, easing) { return values.map(() => easing || easeInOut).splice(0, values.length - 1); } function keyframes({ duration = 300, keyframes: keyframeValues, times, ease = "easeInOut", }) { /** * Easing functions can be externally defined as strings. Here we convert them * into actual functions. */ const easingFunctions = isEasingArray(ease) ? ease.map(easingDefinitionToFunction) : easingDefinitionToFunction(ease); /** * This is the Iterator-spec return value. We ensure it's mutable rather than using a generator * to reduce GC during animation. */ const state = { done: false, value: keyframeValues[0], }; /** * Create a times array based on the provided 0-1 offsets */ const absoluteTimes = convertOffsetToTimes( // Only use the provided offsets if they're the correct length // TODO Maybe we should warn here if there's a length mismatch times && times.length === keyframeValues.length ? times : defaultOffset(keyframeValues), duration); const mapTimeToKeyframe = interpolate(absoluteTimes, keyframeValues, { ease: Array.isArray(easingFunctions) ? easingFunctions : defaultEasing(keyframeValues, easingFunctions), }); return { calculatedDuration: duration, next: (t) => { state.value = mapTimeToKeyframe(t); state.done = t >= duration; return state; }, }; } export { defaultEasing, keyframes };