polate-js
Version:
A numerical and color interpolation utility for Javascript and Typescript.
117 lines (116 loc) • 6.12 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
var colors_util_1 = require("./colors.util");
var validation_util_1 = require("./validation.util");
function findInterpolationRangeStart(inputRange, solveFor) {
var rangeEnd;
for (var i = 0; i < inputRange.length; i++) {
if (inputRange[i] >= solveFor) {
rangeEnd = i;
break;
}
}
return rangeEnd === undefined ? inputRange.length - 2 : Math.max(0, rangeEnd - 1);
}
exports.findInterpolationRangeStart = findInterpolationRangeStart;
function linearInterpolate(inputRange, outputRange, solveFor, extrapolate) {
if (extrapolate === void 0) { extrapolate = "extend"; }
if (inputRange.length !== 2) {
throw new Error("Linear interpolation only works for an input range length of 2.");
}
if (outputRange.length !== 2) {
throw new Error("Linear interpolation only works for an output range length of 2.");
}
if (!inputRange.every(function (o) { return typeof o === "number"; })) {
throw new Error("The values in the input range can only be numbers.");
}
if (!outputRange.every(function (o) { return typeof o === "number"; })) {
throw new Error("The values in the output range can only be numbers.");
}
if (typeof solveFor !== "number") {
throw new Error("The value to solve for can only be a number.");
}
if (!validation_util_1.checkNoInfinityValidity(solveFor, inputRange, outputRange)) {
throw new Error("The values in the input range and output range and the value to solve for cannot include Infinity or -Infinity.");
}
if (!validation_util_1.checkStrictlyIncreasingValidity(inputRange)) {
throw new Error("Values in the input range have to be strictly monotonically increasing.");
}
var inputMin = inputRange[0];
var inputMax = inputRange[inputRange.length - 1];
var outputMin = outputRange[0];
var outputMax = outputRange[outputRange.length - 1];
if (solveFor <= inputMin && extrapolate === "clamp") {
return outputMin;
}
if (solveFor >= inputMax && extrapolate === "clamp") {
return outputMax;
}
var increment = ((solveFor - inputRange[0]) * (outputRange[1] - outputRange[0])) / (inputRange[1] - inputRange[0]);
return outputRange[0] + increment;
}
exports.linearInterpolate = linearInterpolate;
function numericalInterpolate(inputRange, outputRange, solveFor, extrapolate) {
if (extrapolate === void 0) { extrapolate = "extend"; }
if (inputRange.length !== outputRange.length) {
throw new Error("The input range and output range must have equal sizes.");
}
if (!inputRange.every(function (o) { return typeof o === "number"; })) {
throw new Error("The values in the input range can only be numbers.");
}
if (!outputRange.every(function (o) { return typeof o === "number"; })) {
throw new Error("The values in the output range can only be numbers.");
}
if (!validation_util_1.checkNoInfinityValidity(solveFor, inputRange)) {
throw new Error("The values in the input range and the value to solve for cannot include Infinity or -Infinity.");
}
if (!validation_util_1.checkStrictlyIncreasingValidity(inputRange)) {
throw new Error("Values in the input range have to be strictly monotonically increasing.");
}
var interpolationRangeStart = findInterpolationRangeStart(inputRange, solveFor);
return linearInterpolate([inputRange[interpolationRangeStart], inputRange[interpolationRangeStart + 1]], [outputRange[interpolationRangeStart], outputRange[interpolationRangeStart + 1]], solveFor, extrapolate);
}
exports.numericalInterpolate = numericalInterpolate;
function colorInterpolate(inputRange, outputRange, solveFor, extrapolate) {
if (extrapolate === void 0) { extrapolate = "extend"; }
if (inputRange.length !== outputRange.length) {
throw new Error("The input range and output range must have equal sizes.");
}
if (!inputRange.every(function (o) { return typeof o === "number"; })) {
throw new Error("The values in the input range can only be numbers.");
}
if (!outputRange.every(function (o) { return typeof o === "string"; })) {
throw new Error("The values in the output range can only be strings.");
}
if (!outputRange.every(function (o) { return colors_util_1.validateColor(o); })) {
throw new Error("The values in the output range have to be valid hex or rgb colors.");
}
if (!validation_util_1.checkNoInfinityValidity(solveFor, inputRange)) {
throw new Error("The values in the input range and the value to solve for cannot include Infinity or -Infinity.");
}
if (!validation_util_1.checkStrictlyIncreasingValidity(inputRange)) {
throw new Error("Values in the input range have to be strictly monotonically increasing.");
}
var inputMin = inputRange[0];
var inputMax = inputRange[inputRange.length - 1];
var outputMin = outputRange[0];
var outputMax = outputRange[outputRange.length - 1];
if (solveFor <= inputMin && extrapolate === "clamp") {
return outputMin;
}
if (solveFor >= inputMax && extrapolate === "clamp") {
return outputMax;
}
var normalizedValues = outputRange.map(function (o) { return colors_util_1.normalizeColor(o); });
var interpolationRangeStart = findInterpolationRangeStart(inputRange, solveFor);
var interpolatedValues = new Array();
var _loop_1 = function (i) {
var outputRange_1 = normalizedValues.map(function (o) { return o[i]; });
interpolatedValues.push(Math.round(linearInterpolate([inputRange[interpolationRangeStart], inputRange[interpolationRangeStart + 1]], [outputRange_1[interpolationRangeStart], outputRange_1[interpolationRangeStart + 1]], solveFor, extrapolate)));
};
for (var i = 0; i < 3; i++) {
_loop_1(i);
}
return "#" + colors_util_1.convertRgbToHexadecimal(interpolatedValues[0], interpolatedValues[1], interpolatedValues[2]);
}
exports.colorInterpolate = colorInterpolate;