初始化奇妙小屏幕控制器项目

This commit is contained in:
2026-09-08 22:56:52 +08:00
commit 8d368de3b5
491 changed files with 67678 additions and 0 deletions
@@ -0,0 +1,76 @@
export function clamp(value, minimum, maximum) {
return Math.min(maximum, Math.max(minimum, Number(value)));
}
export function normalizeHex(value) {
const match = /^#?([0-9a-f]{6})$/i.exec(String(value).trim());
return match ? `#${match[1].toUpperCase()}` : null;
}
export function rgbToHex({ r, g, b }) {
return `#${[r, g, b]
.map((channel) => Math.round(clamp(channel, 0, 255)).toString(16).padStart(2, "0"))
.join("")}`.toUpperCase();
}
export function hexToRgb(value) {
const hex = normalizeHex(value);
if (!hex) throw new TypeError("颜色必须是 #RRGGBB");
return {
r: Number.parseInt(hex.slice(1, 3), 16),
g: Number.parseInt(hex.slice(3, 5), 16),
b: Number.parseInt(hex.slice(5, 7), 16),
};
}
export function rgbToHsv({ r, g, b }) {
const red = clamp(r, 0, 255) / 255;
const green = clamp(g, 0, 255) / 255;
const blue = clamp(b, 0, 255) / 255;
const maximum = Math.max(red, green, blue);
const minimum = Math.min(red, green, blue);
const delta = maximum - minimum;
let hue = 0;
if (delta !== 0) {
if (maximum === red) hue = 60 * (((green - blue) / delta) % 6);
else if (maximum === green) hue = 60 * ((blue - red) / delta + 2);
else hue = 60 * ((red - green) / delta + 4);
}
if (hue < 0) hue += 360;
return {
h: Math.round(hue),
s: Math.round(maximum === 0 ? 0 : (delta / maximum) * 100),
v: Math.round(maximum * 100),
};
}
export function hsvToRgb({ h, s, v }) {
const hue = ((Number(h) % 360) + 360) % 360;
const saturation = clamp(s, 0, 100) / 100;
const value = clamp(v, 0, 100) / 100;
const chroma = value * saturation;
const segment = hue / 60;
const secondary = chroma * (1 - Math.abs((segment % 2) - 1));
let channels = [0, 0, 0];
if (segment < 1) channels = [chroma, secondary, 0];
else if (segment < 2) channels = [secondary, chroma, 0];
else if (segment < 3) channels = [0, chroma, secondary];
else if (segment < 4) channels = [0, secondary, chroma];
else if (segment < 5) channels = [secondary, 0, chroma];
else channels = [chroma, 0, secondary];
const match = value - chroma;
return {
r: Math.round((channels[0] + match) * 255),
g: Math.round((channels[1] + match) * 255),
b: Math.round((channels[2] + match) * 255),
};
}
export function updateRecentColors(colors, value, limit = 10) {
const normalized = normalizeHex(value);
if (!normalized) return Array.isArray(colors) ? colors.slice(0, limit) : [];
const existing = Array.isArray(colors)
? colors.map(normalizeHex).filter(Boolean).filter((color) => color !== normalized)
: [];
return [normalized, ...existing].slice(0, limit);
}