Add color adaptation functions for theme-based palette adjustments

- Implement rgbToHsl and hslToRgb functions for color space conversions.
- Introduce adaptPalette function to adjust colors based on dark/light themes, enhancing visual consistency.
- Add isDarkTheme function to determine the current theme state, improving theme handling across visual components.
This commit is contained in:
Xin Wang
2026-06-10 09:32:53 +08:00
parent 9327cff364
commit c839779d87

View File

@@ -60,3 +60,69 @@ export function readPalette(el: Element): Palette {
rose: parseHex(s.getPropertyValue("--gradient-rose"), FALLBACK.rose),
};
}
function rgbToHsl({ r, g, b }: RGB): [number, number, number] {
const rn = r / 255;
const gn = g / 255;
const bn = b / 255;
const max = Math.max(rn, gn, bn);
const min = Math.min(rn, gn, bn);
const l = (max + min) / 2;
if (max === min) return [0, 0, l];
const d = max - min;
const s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
let h: number;
if (max === rn) h = (gn - bn) / d + (gn < bn ? 6 : 0);
else if (max === gn) h = (bn - rn) / d + 2;
else h = (rn - gn) / d + 4;
return [h / 6, s, l];
}
function hue2rgb(p: number, q: number, t: number) {
if (t < 0) t += 1;
if (t > 1) t -= 1;
if (t < 1 / 6) return p + (q - p) * 6 * t;
if (t < 1 / 2) return q;
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
return p;
}
function hslToRgb(h: number, s: number, l: number): RGB {
if (s === 0) {
const v = Math.round(l * 255);
return { r: v, g: v, b: v };
}
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
const p = 2 * l - q;
return {
r: Math.round(hue2rgb(p, q, h + 1 / 3) * 255),
g: Math.round(hue2rgb(p, q, h) * 255),
b: Math.round(hue2rgb(p, q, h - 1 / 3) * 255),
};
}
/**
* 按主题为「发光画面」调整调色板:
* 暗色提亮提饱和让辉光透亮;亮色加深加饱和,避免粉彩色在白底上发灰。
*/
export function adaptPalette(palette: Palette, dark: boolean): Palette {
const tune = (c: RGB): RGB => {
const [h, s, l] = rgbToHsl(c);
return dark
? hslToRgb(h, Math.min(1, s * 1.25), Math.min(0.78, l * 1.15))
: hslToRgb(h, Math.min(1, s * 1.55), Math.max(0.36, l * 0.6));
};
return {
sky: tune(palette.sky),
lav: tune(palette.lav),
rose: tune(palette.rose),
};
}
/** 当前是否处于暗色主题(与 ThemeToggle 在 <html> 上切换的 .dark 一致) */
export function isDarkTheme(): boolean {
return (
typeof document !== "undefined" &&
document.documentElement.classList.contains("dark")
);
}