52 lines
1.9 KiB
JavaScript
52 lines
1.9 KiB
JavaScript
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 };
|