123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- const themeColor = {};
- /**
- * 单例模式确保全局只有一个Color实例
- * @param {Object} themeColor 主题颜色
- */
- const Color = (function () {
- let instance;
- return function (themeColor) {
- if (instance) return instance;
- return new ColorConstructor(themeColor);
- };
- })();
- class ColorConstructor {
- // 定义私有属性,用于存储主题颜色和颜色变化程度
- #themeColor; // 主题颜色
- #changeSpan; // 颜色变化程度
- #themeKey; // 主题颜色key
- #subThemeKey; // 辅助颜色key
- #theme; // 主题
- constructor({
- themeColor,
- changeSpan,
- themeKey,
- theme = "light",
- subThemeKey,
- }) {
- // 如果没有传入主题颜色,则抛出错误
- if (!themeColor) throw new Error(`主题颜色是必须的`);
- // 设置主题
- this.setTheme(theme);
- // 设置主题颜色
- this.setThemeColor({
- themeColor,
- changeSpan,
- themeKey,
- theme,
- subThemeKey,
- });
- }
- // 判断颜色是否为16进制颜色
- isHEX(color) {
- // 如果颜色长度不为7或4,则返回false
- if (color.length !== 7 && color.length !== 4) return false;
- // 定义正则表达式,用于匹配16进制颜色
- const hexreg = /^\#?([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$/;
- // 返回正则表达式匹配结果
- return hexreg.test(color);
- }
- isRGB(color) {
- const rgbreg = /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/;
- return rgbreg.test(color);
- }
- // 格式化十六进制颜色值
- formatHex(hex) {
- // 如果长度不等于4,则返回原值
- if (hex.length !== 4) return hex;
- // 返回格式化后的十六进制颜色值
- return `#${hex[1]}${hex[1]}${hex[2]}${hex[2]}${hex[3]}${hex[3]}`;
- }
- // 参数归一化颜色
- normalizeColor(color) {
- let colorMap = {};
- if (typeof color === "string") {
- if (!this.isHEX(color) && !this.isRGB(color)) {
- throw new Error(`颜色值${color}格式不正确`);
- }
- colorMap[this.#themeKey] = color;
- } else if (Object.prototype.toString.call(color) !== "[object Object]") {
- throw new Error(`颜色值${color}格式不正确 必须是字符串或者对象的形式`);
- } else {
- colorMap = color;
- }
- return colorMap;
- }
- // 设置主题颜色
- setThemeColor({
- themeColor,
- changeSpan = 0.2,
- themeKey = "primary",
- subThemeKey = "success",
- onSuccess,
- }) {
- // 将传入的颜色赋值给私有属性#themeColor
- const newTheme = this.normalizeColor(themeColor);
- this.#changeSpan = changeSpan;
- this.#themeColor = this.#setThemeMap(newTheme, this.#changeSpan);
- this.#themeKey = themeKey;
- this.#subThemeKey = subThemeKey;
- onSuccess?.(this.#themeColor);
- }
- // 设置主题
- setTheme(theme) {
- if (theme !== "dark" && theme !== "light")
- throw new Error(`主题必须是dark或者light`);
- // 将传入的主题赋值给私有属性#theme
- this.#theme = theme;
- // 调用私有方法#setThemeMap,传入私有属性#themeColor和#changeSpan,将返回值赋值给私有属性#themeColor
- this.#themeColor = this.#setThemeMap(this.#themeColor, this.#changeSpan);
- }
- // 获取主题颜色
- get themeColor() {
- // 返回主题颜色
- return this.#themeColor[this.#themeKey];
- }
- // 获取子主题颜色
- get subThemeColor() {
- // 返回主题颜色中子主题键对应的颜色值
- return this.#themeColor[this.#subThemeKey];
- }
- // 获取变淡以及加深的颜色
- #setThemeMap(themeColor, changeSpan) {
- const newTheme = { ...themeColor };
- const changeList = new Array(5)
- .fill(0)
- .map((_, index) => index * changeSpan)
- .filter((item) => item > 0 && item < 1);
- for (const key in newTheme) {
- changeList.forEach((item, index) => {
- newTheme[`${key}-light-${index + 1}`] = this.getLightColor(
- newTheme[key],
- item
- );
- newTheme[`${key}-dark-${index + 1}`] = this.getDarkColor(
- newTheme[key],
- item
- );
- });
- }
- return newTheme;
- }
- // 获取主题颜色 1-4 或者 空
- getThemeColor(index, themeKey = this.#themeKey) {
- // 打印深色主题颜色
- const key = `${themeKey}${!!index ? `-${this.#theme}-${index}` : ""}`;
- return this.#themeColor[key];
- }
- //16进制颜色转GRB颜色
- HexToRgb(str) {
- if (!this.isHEX(str)) {
- return;
- }
- str = this.formatHex(str);
- let hexs = null;
- str = str.replace("#", ""); // 去掉#
- hexs = str.match(/../g); // 切割成数组 409EFF => ['40','9E','FF']
- // 将切割的色值转换为16进制
- for (let i = 0; i < hexs.length; i++) hexs[i] = parseInt(hexs[i], 16);
- return hexs;
- }
- //GRB颜色转16进制颜色
- rgbaToHex(rgba) {
- let hex = "#";
- for (const i of rgba) {
- hex += i.toString(16).padStart(2, "0");
- }
- return hex;
- }
- // 计算颜色
- computedColor(color, fn) {
- // 将颜色转换为rgb格式
- let rgb = color;
- if (this.isHEX(color)) {
- rgb = this.HexToRgb(color);
- }
- // 创建一个空数组,用于存储转换后的颜色值
- let sColorChange = [];
- // 遍历rgb数组
- for (var i = 0; i < rgb.length; i++) {
- // 对每个颜色值进行转换
- let val = fn(rgb[i]);
- // 如果转换后的值小于0,则将其设置为0
- if (val < 0) {
- val = 0;
- }
- // 如果转换后的值大于255,则将其设置为255
- if (val > 255) {
- val = 255;
- }
- // 将转换后的值添加到数组中
- sColorChange.push(val);
- }
- // 将转换后的rgb数组转换为hex格式
- return this.rgbaToHex(sColorChange);
- }
- //得到16进制颜色值为color的加深颜色值,level为加深的程度,限0-1之间
- getDarkColor(color, level) {
- return this.computedColor(color, (item) => item - Math.floor(item * level));
- }
- //得到16进制颜色值为color的减淡颜色值,level为加深的程度,限0-1之间
- getLightColor(color, level) {
- return this.computedColor(color, (item) => item + Math.floor(item * level));
- }
- }
- export default new Color({ themeColor });
|