Color interpolation in HSB - how to go the "closest" direction?

Hi! I am exploring doing some color gradients in something I am working on. I generally have the core structure working well, defining multiple colors and using lerpColor() to linearly interpolate between them.

The challenge I see is that lerpColor() seems to not behave “well” under certain conditions. As a simple example, let’s say I want to interpolate between #ffafbd#ffc3a0. One might argue that the most sensible interpolation between these colors would stay entirely within the pink/orange spectrum, as the colors are actually quite close to each other. However, if you lerpColor() between these two, the linear interpolation will do a full trip around the entire hue spectrum.

I presume the reason for this is that if hue 1 is close to zero, and hue 2 is close to 360, the interpolator will not “wrap around” from 0 to 360, but rather traverse the longer path without wrapping.

Are there any build in functions that optimize the linear interpolation across this “shortest” color path? I would strongly prefer to stick with HSB color space since it is much easier to reason through in generative art. Would love any advice on better ways to deal with this aside from just writing my own color interpolation function.

I think it’s the “expected” behavior. As in the reference, even when colorMode is HSB, lerpColor will simply interpolate the values.

simple lerp example: p5.js Web Editor

Unfortunately you need to write your own function (or find another library) to achieve the shortest path. I found a snippet on stackoverflow and adapted it (using the new lerp function, top is red to green, bottom is red to pink)

https://editor.p5js.org/micuat/sketches/p0opDaFfL

I think lerp works better in RGB for colors that are perceptually similar:

function setup() {
  createCanvas(400, 400);
  colorMode(HSB, 360);
  const c0 = color('#ffafbd');
  console.log(hue(c0));
  const c1 = color('#ffc3a0');
  console.log(hue(c1));
  for(let x = 0; x < width; x++) {
    colorMode(RGB);
    stroke(lerpColor(c0, c1, x/width));
    line(x, 0, x, height/2);
    colorMode(HSB, 360);
    stroke(lerpColor(c0, c1, x/width));
    line(x, height/2, x, height);
  }
}