RSS Amplifier

J Lopes — Developer Portfolio & Creative Writings · Nov 15, 2024

Colour Palette Generator

0
Sign in to vote or save

jlopes.eu


This started as a CodePen sketch: a colour palette generator that could do more than spit out random colours. I wanted something that could generate harmonious palettes, find the middle colour between any two shades, and convert between RGB (Red/Green/Blue), HSL (Hue/Saturation/Lightness), and hex on the fly. The kind of thing that’s actually useful for design work.

Starting with colour harmony

First, the generator picks a random starting point on the colour wheel1 (0-360 degrees). This base hue becomes the foundation for the entire palette.

const base = Math.floor(Math.random() * 360);

Instead of generating completely random colors, each subsequent color is a variation of the base one, spaced 30 degrees apart on the color wheel. The hue variation is wrapped around the colour wheel using modulo arithmetic2, so that it stays in between 360 degrees. Saturation and lightness are randomized within ranges that avoid pastels and darker colors. To simplify complementary colour calculations we use HSL as the base colour model.

const hue = (base + variation * 30) % 360;
const saturation = 70 + Math.random() * 30;
const lightness = Math.random() * 80;

But how can we find the middle colour?

Short answer: “interpolation”.

For saturation and lightness, finding the middle is straightforward. We can calculate the averages between:

let saturation = Math.round((s1 + s2) / 2);
let lightness = Math.round((l1 + l2) / 2);

Hue is different, however. Hue exists on a circular range. If we averaged 10° (red) and 350° (also red), we’d get 180° (cyan). Not quite red.

The fix is to check whether the two hues are more than 180° apart and add 360° to the smaller one. That pulls both values closer together in the spectrum, so the interpolated colour lands between them.

let diff = Math.abs(h2 - h1);
if (diff > 180) {
if (h1 < h2) {
  h1 += 360;
} else {
  h2 += 360;
}
}
let hue = Math.round((h1 + h2) / 2) % 360;

Converting between colour models

Different contexts need different color formats. So why not provide them all?

HSL to RGB

This function divides the color wheel into segments and calculates each RGB component based on where the hue falls within those segments. The k function maps the hue position, and f computes the actual color value with proper saturation and lightness adjustments.

(I didn’t make this conversion formula, smarter people did3)

const toRGB = (h, s, l, a = 1) => {
s /= 100;
l /= 100;
const k = (n) => (n + h / 30) % 12;
const f = (n) =>
  l - s * Math.min(l, 1 - l) * Math.max(-1, Math.min(k(n) - 3, 9 - k(n), 1));
return [
  Math.round(255 * f(0)), // Red
  Math.round(255 * f(8)), // Green
  Math.round(255 * f(4)), // Blue
  a,                      // Alpha
];
};

HSL to Hex

Once you have the RGB values, convert each number to hexadecimal and concatenate. (I also stole this solution4)

const toHex = (h, s, l) => {
l /= 100;
const a = (s * Math.min(l, 1 - l)) / 100;
const f = (n) => {
  const k = (n + h / 30) % 12;
  const color = l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
  return Math.round(255 * color)
    .toString(16)
    .padStart(2, '0');
};
return `#${f(0)}${f(8)}${f(4)}`;
};

Add Colors Between, or interpolate middle colours

Click the ”+” button between any two colors, and an interpolated colour appears between both. You can keep clicking to subdivide the palette into smoother gradients. For colors in the middle of your palette, there’s an interpolate button that recalculates that color as the perfect blend of its neighbors.

Randomize Colors

There are randomize buttons for individual colours, or the whole palette.

Copy in Multiple Formats

Click any color value to copy it. The tool shows all three formats at once, and clicking any one copies it to your clipboard.

The standalone version

I later rebuilt this as a proper tool. Same logic underneath, but quicker to use: hit space for a new palette, or feed it an image and it pulls the colours out as hex.

References

  1. Colour wheelen.wikipedia.org
  2. Modulo arithmeticstackoverflow.com
  3. Smarter people didw3.org
  4. Stole this solutionstackoverflow.com

Read the original on jlopes.eu

Comments

Nothing yet. Say the first thing.

    Sign in to join the conversation.