2025-03-24 22:56:10 +01:00

90 lines
3.1 KiB
JavaScript

import { progress } from './progress';
import { mix } from './mix';
import { mixColor } from './mix-color';
import { mixComplex, mixArray, mixObject } from './mix-complex';
import { color } from 'style-value-types';
import { clamp } from './clamp';
import { pipe } from './pipe';
import { invariant } from 'hey-listen';
const mixNumber = (from, to) => (p) => mix(from, to, p);
function detectMixerFactory(v) {
if (typeof v === 'number') {
return mixNumber;
}
else if (typeof v === 'string') {
if (color.test(v)) {
return mixColor;
}
else {
return mixComplex;
}
}
else if (Array.isArray(v)) {
return mixArray;
}
else if (typeof v === 'object') {
return mixObject;
}
}
function createMixers(output, ease, customMixer) {
const mixers = [];
const mixerFactory = customMixer || detectMixerFactory(output[0]);
const numMixers = output.length - 1;
for (let i = 0; i < numMixers; i++) {
let mixer = mixerFactory(output[i], output[i + 1]);
if (ease) {
const easingFunction = Array.isArray(ease) ? ease[i] : ease;
mixer = pipe(easingFunction, mixer);
}
mixers.push(mixer);
}
return mixers;
}
function fastInterpolate([from, to], [mixer]) {
return (v) => mixer(progress(from, to, v));
}
function slowInterpolate(input, mixers) {
const inputLength = input.length;
const lastInputIndex = inputLength - 1;
return (v) => {
let mixerIndex = 0;
let foundMixerIndex = false;
if (v <= input[0]) {
foundMixerIndex = true;
}
else if (v >= input[lastInputIndex]) {
mixerIndex = lastInputIndex - 1;
foundMixerIndex = true;
}
if (!foundMixerIndex) {
let i = 1;
for (; i < inputLength; i++) {
if (input[i] > v || i === lastInputIndex) {
break;
}
}
mixerIndex = i - 1;
}
const progressInRange = progress(input[mixerIndex], input[mixerIndex + 1], v);
return mixers[mixerIndex](progressInRange);
};
}
export function interpolate(input, output, { clamp: isClamp = true, ease, mixer } = {}) {
const inputLength = input.length;
invariant(inputLength === output.length, 'Both input and output ranges must be the same length');
invariant(!ease || !Array.isArray(ease) || ease.length === inputLength - 1, 'Array of easing functions must be of length `input.length - 1`, as it applies to the transitions **between** the defined values.');
if (input[0] > input[inputLength - 1]) {
input = [].concat(input);
output = [].concat(output);
input.reverse();
output.reverse();
}
const mixers = createMixers(output, ease, mixer);
const interpolator = inputLength === 2
? fastInterpolate(input, mixers)
: slowInterpolate(input, mixers);
return isClamp
? (v) => interpolator(clamp(input[0], input[inputLength - 1], v))
: interpolator;
}
//# sourceMappingURL=interpolate.js.map