How to Smoothly Interpolate Between Two Angles In JavaScript

Interpolating angles can be a tricky process, especially when dealing with 2D rotations where angles wrap around after 360 degrees (or (2\pi) radians). One common challenge developers face is ensuring the rotation takes the shortest path. For example, if you want to interpolate from 350° to 10°, you’d want the rotation to go from 350°, 360°, and then to 10°, rather than going all the way back through 0°.

This post will introduce a simple, portable, and easy-to-remember method for 2D angle interpolation that accounts for the shortest distance.

The Code

function shortAngleDist(a0,a1) {
    var max = Math.PI*2;
    var da = (a1 - a0) % max;
    return 2*da % max - da;
}

function angleLerp(a0,a1,t) {
    return a0 + shortAngleDist(a0,a1)*t;
}

How It Works

shortAngleDist(a0, a1)

This function calculates the shortest distance between two angles a0 and a1 .

  • max = Math.PI*2; : Defines the maximum value for our angles in radians, which is (2\pi).
  • da = (a1 - a0) % max; : Calculates the difference between the two angles and wraps it around using modulo to ensure it lies within the range of [0, (2\pi)].
  • return 2*da % max - da; : The magic line! It ensures the returned distance is the shortest path between the two angles.

angleLerp(a0, a1, t)

This function linearly interpolates between two angles a0 and a1 based on the interpolation factor t .

  • return a0 + shortAngleDist(a0,a1)*t; : This returns the interpolated angle by adding the starting angle a0 and the product of the shortest angle distance and the interpolation factor t .

Benefits

  1. No Need for Normalization : The angles passed to the functions don’t need to be normalized. The functions handle angles beyond the [0, (2\pi)] range.
  2. Portability : The implementation is designed to be portable and works irrespective of how the modulo “%” operator outputs sign in different languages like Python, Ruby, or JavaScript.
  3. Easy to Remember : Thanks to its simplicity and clarity.

Usage

To use this script, simply call the angleLerp function with your starting angle, ending angle, and interpolation factor.

var startAngle = Math.PI / 4;   // 45 degrees in radians
var endAngle = 3 * Math.PI / 2; // 270 degrees in radians
var t = 0.5;                    // halfway

var interpolatedAngle = angleLerp(startAngle, endAngle, t);
console.log(interpolatedAngle); // This will give you the angle halfway between startAngle and endAngle, taking the shortest path.

Conclusion

Interpolating angles in 2D can be a breeze with the right approach. This method, credited to Trey Wilson for the closed-form solution for shortAngleDist , offers a straightforward way to ensure rotations are smooth and take the shortest path. Whether you’re working on animations, game development, or any other application that requires angle interpolation, this method is a valuable tool to have in your arsenal.

5 Likes