UNPKG

create-expo-cljs-app

Version:

Create a react native application with Expo and Shadow-CLJS!

155 lines (139 loc) 4.21 kB
import { lessThan, multiply, sub, add, divide, greaterThan, lessOrEq, eq, } from '../operators'; import invariant from 'invariant'; import AnimatedNode from '../core/AnimatedNode'; import { createAnimatedCond as cond } from '../core/AnimatedCond'; import { createAnimatedFunction as proc } from '../core/AnimatedFunction'; const interpolateInternalSingleProc = proc(function ( value, inS, inE, outS, outE ) { const progress = divide(sub(value, inS), sub(inE, inS)); // logic below was made in order to provide a compatibility witn an Animated API const resultForNonZeroRange = add(outS, multiply(progress, sub(outE, outS))); const result = cond( eq(inS, inE), cond(lessOrEq(value, inS), outS, outE), resultForNonZeroRange ); return result; }); function interpolateInternalSingle(value, inputRange, outputRange, offset) { const inS = inputRange[offset]; const inE = inputRange[offset + 1]; const outS = outputRange[offset]; const outE = outputRange[offset + 1]; return interpolateInternalSingleProc(value, inS, inE, outS, outE); } function interpolateInternal(value, inputRange, outputRange, offset = 0) { if (inputRange.length - offset === 2) { return interpolateInternalSingle(value, inputRange, outputRange, offset); } return cond( lessThan(value, inputRange[offset + 1]), interpolateInternalSingle(value, inputRange, outputRange, offset), interpolateInternal(value, inputRange, outputRange, offset + 1) ); } export const Extrapolate = { EXTEND: 'extend', CLAMP: 'clamp', IDENTITY: 'identity', }; function checkNonDecreasing(name, arr) { for (let i = 1; i < arr.length; ++i) { // We can't validate animated nodes in JS. if (arr[i] instanceof AnimatedNode || arr[i - 1] instanceof AnimatedNode) continue; invariant( arr[i] >= arr[i - 1], '%s must be monotonically non-decreasing. (%s)', name, arr ); } } function checkMinElements(name, arr) { invariant( arr.length >= 2, '%s must have at least 2 elements. (%s)', name, arr ); } function checkValidNumbers(name, arr) { for (let i = 0; i < arr.length; i++) { // We can't validate animated nodes in JS. if (arr[i] instanceof AnimatedNode || typeof arr[i] !== 'number') continue; invariant( Number.isFinite(arr[i]), '%s cannot include %s. (%s)', name, arr[i], arr ); } } function convertToRadians(outputRange) { for (const [i, value] of outputRange.entries()) { if (typeof value === 'string' && value.endsWith('deg')) { outputRange[i] = parseFloat(value) * (Math.PI / 180); } else if (typeof value === 'string' && value.endsWith('rad')) { outputRange[i] = parseFloat(value); } } } export default function interpolate(value, config) { const { inputRange, outputRange, extrapolate = Extrapolate.EXTEND, extrapolateLeft, extrapolateRight, } = config; checkMinElements('inputRange', inputRange); checkValidNumbers('inputRange', inputRange); checkMinElements('outputRange', outputRange); checkValidNumbers('outputRange', outputRange); checkNonDecreasing('inputRange', inputRange); invariant( inputRange.length === outputRange.length, 'inputRange and outputRange must be the same length.' ); convertToRadians(outputRange); const left = extrapolateLeft || extrapolate; const right = extrapolateRight || extrapolate; let output = interpolateInternal(value, inputRange, outputRange); if (left === Extrapolate.EXTEND) { } else if (left === Extrapolate.CLAMP) { output = cond(lessThan(value, inputRange[0]), outputRange[0], output); } else if (left === Extrapolate.IDENTITY) { output = cond(lessThan(value, inputRange[0]), value, output); } if (right === Extrapolate.EXTEND) { } else if (right === Extrapolate.CLAMP) { output = cond( greaterThan(value, inputRange[inputRange.length - 1]), outputRange[outputRange.length - 1], output ); } else if (right === Extrapolate.IDENTITY) { output = cond( greaterThan(value, inputRange[inputRange.length - 1]), value, output ); } return output; }