front/src/utils/themeColor.ts
2026-01-31 15:32:12 +08:00

75 lines
2.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 主题色工具:根据取色器选中的主色,计算 hover/light 并写入 :root CSS 变量
* 用于导航栏、侧边菜单、按钮等公共颜色统一切换
*/
const STORAGE_KEY = 'app-theme-color';
export function getStoredThemeColor(): string | null {
try {
return localStorage.getItem(STORAGE_KEY);
} catch {
return null;
}
}
export function setStoredThemeColor(hex: string): void {
try {
localStorage.setItem(STORAGE_KEY, hex);
} catch {
// ignore
}
}
/** 将 hex 转为 r,g,b (0-255) */
function hexToRgb(hex: string): { r: number; g: number; b: number } | null {
const m = hex.replace(/^#/, '').match(/^([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i);
if (!m) return null;
return {
r: parseInt(m[1], 16),
g: parseInt(m[2], 16),
b: parseInt(m[3], 16),
};
}
/** 将 r,g,b 转为 #rrggbb */
function rgbToHex(r: number, g: number, b: number): string {
return '#' + [r, g, b].map((x) => Math.round(Math.max(0, Math.min(255, x))).toString(16).padStart(2, '0')).join('');
}
/** 在 hex 颜色基础上按比例变暗(用于 hover) */
function darkenHex(hex: string, ratio: number): string {
const rgb = hexToRgb(hex);
if (!rgb) return hex;
return rgbToHex(rgb.r * (1 - ratio), rgb.g * (1 - ratio), rgb.b * (1 - ratio));
}
/** 生成浅色背景(用于 menu hover 等) */
function lightenHex(hex: string, mixWhite = 0.92): string {
const rgb = hexToRgb(hex);
if (!rgb) return hex;
const r = Math.round(rgb.r * (1 - mixWhite) + 255 * mixWhite);
const g = Math.round(rgb.g * (1 - mixWhite) + 255 * mixWhite);
const b = Math.round(rgb.b * (1 - mixWhite) + 255 * mixWhite);
return rgbToHex(r, g, b);
}
/**
* 将主题色应用到页面:设置 :root 上的 CSS 变量
* @param primaryHex 主色,如 #2D8C8C
*/
export function applyThemeColor(primaryHex: string): void {
const hex = primaryHex.startsWith('#') ? primaryHex : `#${primaryHex}`;
const root = document.documentElement;
const primary = hex;
const primaryHover = darkenHex(hex, 0.05);
const primaryLight = lightenHex(hex, 0.92);
root.style.setProperty('--app-primary-color', primary);
root.style.setProperty('--app-primary-color-hover', primaryHover);
root.style.setProperty('--app-primary-color-light', primaryLight);
root.style.setProperty('--app-navbar-bg', primary);
root.style.setProperty('--app-sidebar-bg', primary);
}