DEV Community

Pablo Garcia
Pablo Garcia

Posted on

Normalizing or interpolating values in JavaScript/TypeScript

These are three common normalizing functions I use in JavaScript when working with CSS animations/transitions, especially when playing with motion sensors.

Standard Normalization

This function scales a number so that it falls within a standard range of 0 to 1. This is the common meaning of "normalization" in data processing.

Commonly used in data processing and analysis to standardize different sets of data on a common scale, such as in machine learning feature scaling.

function normalize(
  value: number, 
  minValue: number, 
  maxValue: number
): number {
    if (maxValue === minValue) {
        return value === minValue ? 1 : 0;
    }
    return (value - minValue) / (maxValue - minValue);
}

// Example Usage
console.log(normalize(15, 10, 20)); // 0.5
console.log(normalize(30, 20, 40)); // 0.5
Enter fullscreen mode Exit fullscreen mode

Linear Interpolation

This function maps a number from one range to another. It's a form of linear interpolation.

Useful for scaling values, normalizing data to a different range, or converting between different measurement scales.

function linearInterpolation(
  value: number,
  originLowerBound: number,
  originUpperBound: number,
  targetLowerBound: number,
  targetUpperBound: number
): number {
  // Note: we should use the `normalize` function above
  // const ratio = normalize(value, originLowerBound, originUpperBound)
  const ratio =
    (value - originLowerBound) / (originUpperBound - originLowerBound);
  return ratio * (targetUpperBound - targetLowerBound) + targetLowerBound;
}

// Example Usage
const mappedValue = linearInterpolation(5, 0, 10, 0, 100);
console.log(mappedValue); // Should output 50
Enter fullscreen mode Exit fullscreen mode

For example: [1,5] & [10,50] ranges.

  • 1 outputs 10
  • 2 outputs 20
  • ...

Modular Arithmetic-Based Wrapping

This function ensures that a given value is wrapped within a specified numeric range. If the value exceeds the range, it wraps around within this range using modular arithmetic.

Ideal for cyclic or repeating ranges, like angles (think CSS transformations from 0 to 360 degrees), hours on a clock, or other periodic values.

function cyclicInterpolation(
  value: number,
  lowerBound: number,
  upperBound: number
): number {
  // adding 1 to include the upper bound in the range
  const shiftedUpperBound = upperBound - lowerBound + 1;
  const shiftedValue = value - lowerBound;
  return (
    lowerBound +
    // adding parenthesis for emphasis
    (((shiftedValue % shiftedUpperBound) + shiftedUpperBound) %
      shiftedUpperBound)
  );
}

// Example Usage
console.log(cyclicInterpolation(5, 3, 7)); // Outputs 5
console.log(cyclicInterpolation(6, 3, 7)); // Outputs 6
console.log(cyclicInterpolation(7, 3, 7)); // Outputs 7
console.log(cyclicInterpolation(8, 3, 7)); // Outputs 3 - restarts cycle
Enter fullscreen mode Exit fullscreen mode

For example: [1,10]

  • 1 outputs 1
  • 9 outputs 9
  • 10 outputs 10
  • 11 outputs 1 - going back to the beginning

Top comments (0)