67 lines
2.0 KiB
JavaScript
67 lines
2.0 KiB
JavaScript
// Hex → RGB
|
|
export function hexToRgb(hex) {
|
|
const h = hex.replace('#', '');
|
|
if (!/^[0-9a-fA-F]{3}$/.test(h) && !/^[0-9a-fA-F]{6}$/.test(h)) return null;
|
|
const n = parseInt(h.length === 3
|
|
? h.split('').map(c => c + c).join('')
|
|
: h, 16);
|
|
return { r: (n >> 16) & 255, g: (n >> 8) & 255, b: n & 255 };
|
|
}
|
|
|
|
// RGB → Hex
|
|
export function rgbToHex({ r, g, b }) {
|
|
return '#' + [r, g, b].map(v => v.toString(16).padStart(2, '0')).join('');
|
|
}
|
|
|
|
// RGB → HSL (h: 0-360, s: 0-100, l: 0-100)
|
|
export function rgbToHsl({ r, g, b }) {
|
|
r /= 255; g /= 255; b /= 255;
|
|
const max = Math.max(r, g, b), min = Math.min(r, g, b);
|
|
let h = 0, s = 0;
|
|
const l = (max + min) / 2;
|
|
if (max === min) {
|
|
// h and s remain 0 (achromatic)
|
|
} else {
|
|
const d = max - min;
|
|
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
switch (max) {
|
|
case r: h = ((g - b) / d + (g < b ? 6 : 0)) / 6; break;
|
|
case g: h = ((b - r) / d + 2) / 6; break;
|
|
case b: h = ((r - g) / d + 4) / 6; break;
|
|
}
|
|
}
|
|
return { h: Math.round(h * 360), s: Math.round(s * 100), l: Math.round(l * 100) };
|
|
}
|
|
|
|
// HSL → RGB
|
|
export function hslToRgb({ h, s, l }) {
|
|
s /= 100; l /= 100;
|
|
const k = n => (n + h / 30) % 12;
|
|
const a = s * Math.min(l, 1 - l);
|
|
const f = n => l - a * Math.max(-1, Math.min(k(n) - 3, Math.min(9 - k(n), 1)));
|
|
return { r: Math.round(f(0) * 255), g: Math.round(f(8) * 255), b: Math.round(f(4) * 255) };
|
|
}
|
|
|
|
// HSL → Hex
|
|
export function hslToHex(hsl) {
|
|
return rgbToHex(hslToRgb(hsl));
|
|
}
|
|
|
|
// Hex → HSL
|
|
export function hexToHsl(hex) {
|
|
const rgb = hexToRgb(hex);
|
|
if (!rgb) return null;
|
|
return rgbToHsl(rgb);
|
|
}
|
|
|
|
// Harmonien — Input: HSL, Output: Objekt mit Arrays von HSL-Objekten
|
|
export function getHarmonies(hsl) {
|
|
const rotate = deg => ({ ...hsl, h: (hsl.h + deg + 360) % 360 });
|
|
return {
|
|
komplementaer: [rotate(180)],
|
|
analog: [rotate(-30), rotate(30)],
|
|
triade: [rotate(120), rotate(240)],
|
|
splitKomplementaer: [rotate(150), rotate(210)],
|
|
};
|
|
}
|