90 lines
3.1 KiB
JavaScript
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
|