Skip to content

Color scales: gradient-like interpolation across multiple color stops #506

@LeaVerou

Description

@LeaVerou

Currently we have Color.range() and friends which only interpolates between 2 colors. I just had to write this for a color component I’m writing (<color-slider>), and it was no fun:

colorAt (p) {
	let bands = this.scales?.length;

	if (bands <= 0) {
		return null;
	}

	// FIXME the values outside of [0, 1] should be scaled
	if (p >= 1) {
		return this.scales.at(-1)(p);
	}
	else if (p <= 0) {
		return this.scales[0](p);
	}

	let band = 1 / bands;
	let scaleIndex = Math.max(0, Math.min(Math.floor(p / band), bands - 1));
	let scale = this.scales[scaleIndex];
	let color = scale((p % band) * bands);

	return color;
}

And this is just equally spaced color stops. I dread to think about implementing the general case.
Which is why I think Color.js should provide it 😁

I’m thinking of something like:

/**
  @param {Array<Color | {color: Color, at: number}>} stops
  @param {RangeOptions} [options]
 */
function colorScale(colors: Array<Color>, options): function;

Thoughts?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions