ph-utils 0.20.0 → 0.20.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/dom.js +28 -18
- package/lib/src/array.d.ts +79 -0
- package/lib/src/array.js +212 -0
- package/lib/src/color.d.ts +55 -0
- package/lib/src/color.js +294 -0
- package/lib/src/config.d.ts +33 -0
- package/lib/src/config.js +99 -0
- package/lib/src/copy.d.ts +11 -0
- package/lib/src/copy.js +101 -0
- package/lib/src/crypto.d.ts +74 -0
- package/lib/src/crypto.js +261 -0
- package/lib/src/crypto_node.d.ts +61 -0
- package/lib/src/crypto_node.js +133 -0
- package/lib/src/date.d.ts +66 -0
- package/lib/src/date.js +202 -0
- package/lib/src/dom.d.ts +265 -0
- package/lib/src/dom.js +635 -0
- package/lib/src/file.d.ts +29 -0
- package/lib/src/file.js +54 -0
- package/lib/src/id.d.ts +68 -0
- package/lib/src/id.js +170 -0
- package/lib/src/index.d.ts +154 -0
- package/lib/src/index.js +239 -0
- package/lib/src/logger.d.ts +62 -0
- package/lib/src/logger.js +122 -0
- package/lib/src/server.d.ts +33 -0
- package/lib/src/server.js +65 -0
- package/lib/src/storage.d.ts +51 -0
- package/lib/src/storage.js +73 -0
- package/lib/src/theme.d.ts +44 -0
- package/lib/src/theme.js +156 -0
- package/lib/src/validator.d.ts +71 -0
- package/lib/src/validator.js +238 -0
- package/lib/src/web.d.ts +30 -0
- package/lib/src/web.js +100 -0
- package/package.json +1 -1
package/lib/dom.js
CHANGED
|
@@ -166,19 +166,24 @@ export function replaceClass(el, oldClazz, newClazz) {
|
|
|
166
166
|
* @param {boolean} option 是否是只运行一次的处理函数或者配置,其中 eventFlag 为 string,如果配置该项,则表明为委托事件
|
|
167
167
|
*/
|
|
168
168
|
export function on(element, listener, fn, option) {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
else if (element) {
|
|
178
|
-
if (typeof option === "object" && option.eventFlag) {
|
|
179
|
-
element.setAttribute(option.eventFlag, "__stop__");
|
|
169
|
+
// 提取公共的绑定逻辑
|
|
170
|
+
const addListener = (el) => {
|
|
171
|
+
// 重要:只有 Element (包含 HTMLElement) 才有 setAttribute 方法
|
|
172
|
+
// Document 和 ShadowRoot 是没有 setAttribute 的,必须做类型守卫
|
|
173
|
+
if (typeof option === "object" && option?.eventFlag && el instanceof Element) {
|
|
174
|
+
el.setAttribute(option.eventFlag, "__stop__");
|
|
180
175
|
}
|
|
181
|
-
|
|
176
|
+
el.addEventListener(listener, fn, option);
|
|
177
|
+
};
|
|
178
|
+
// 核心识别逻辑:
|
|
179
|
+
// 如果是 Node 实例,说明是单一节点(HTMLElement, Document, ShadowRoot 都是 Node)
|
|
180
|
+
if (element instanceof Node) {
|
|
181
|
+
addListener(element);
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
// 否则,说明是 HTMLCollection、NodeList 或 Array,直接遍历
|
|
185
|
+
// (即使 length 为 0,iterate 内部通常也会安全跳过,不需要在外部判断 length > 0)
|
|
186
|
+
iterate(element, addListener);
|
|
182
187
|
}
|
|
183
188
|
}
|
|
184
189
|
/**
|
|
@@ -188,13 +193,18 @@ export function on(element, listener, fn, option) {
|
|
|
188
193
|
* @param fn - 要移除的事件监听器函数。
|
|
189
194
|
*/
|
|
190
195
|
export function off(el, listener, fn, option) {
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
196
|
+
// 提取公共的解绑逻辑
|
|
197
|
+
// HTMLElement、Document、ShadowRoot 本质上都实现了 EventTarget 接口
|
|
198
|
+
const removeListener = (target) => {
|
|
199
|
+
target.removeEventListener(listener, fn, option);
|
|
200
|
+
};
|
|
201
|
+
// 核心判断:只要是 Node,就是单一节点
|
|
202
|
+
if (el instanceof Node) {
|
|
203
|
+
removeListener(el);
|
|
195
204
|
}
|
|
196
|
-
else
|
|
197
|
-
|
|
205
|
+
else {
|
|
206
|
+
// 否则就是集合(HTMLCollection / NodeList / Array),直接遍历
|
|
207
|
+
iterate(el, removeListener);
|
|
198
208
|
}
|
|
199
209
|
}
|
|
200
210
|
/**
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 数组排序
|
|
3
|
+
* @param arr 待排序数组
|
|
4
|
+
* @param order 排序信息, asc - 升序, desc - 倒序
|
|
5
|
+
* @param orderKey 如果是个对象数组,按哪个字段排序
|
|
6
|
+
* @returns
|
|
7
|
+
*/
|
|
8
|
+
export declare function order<T>(arr: T[], order?: "asc" | "desc", orderKey?: string | null): T[];
|
|
9
|
+
/**
|
|
10
|
+
* 返回一个所有集合交集的新集合
|
|
11
|
+
*
|
|
12
|
+
* 如果集合本身支持 intersection, 则调用原生 intersection 函数
|
|
13
|
+
*
|
|
14
|
+
* @param arrs
|
|
15
|
+
*
|
|
16
|
+
* @returns 新集合中的元素在传入的所有集合中同时存在
|
|
17
|
+
*/
|
|
18
|
+
export declare function intersection<T>(...arrs: Set<T>[]): Set<T>;
|
|
19
|
+
/**
|
|
20
|
+
* 返回一个所有列表交集的新列表
|
|
21
|
+
*
|
|
22
|
+
* @param arrs
|
|
23
|
+
*
|
|
24
|
+
* @returns 新列表中的元素在传入的所有列表中同时存在
|
|
25
|
+
*/
|
|
26
|
+
export declare function intersection<T>(...arrs: T[][]): T[];
|
|
27
|
+
/**
|
|
28
|
+
* 返回一个包含第一个集合中的元素但不包含后续给定集合中元素的新集合
|
|
29
|
+
*
|
|
30
|
+
* 如果集合本身支持 difference 方法,则调用原生 difference 方法
|
|
31
|
+
*
|
|
32
|
+
* @param arrs 集合列表
|
|
33
|
+
*
|
|
34
|
+
* @returns
|
|
35
|
+
*/
|
|
36
|
+
export declare function difference<T>(...arrs: Set<T>[]): Set<T>;
|
|
37
|
+
/**
|
|
38
|
+
* 返回一个包含第一个列表中的元素但不包含后续给定列表中元素的新列表
|
|
39
|
+
*
|
|
40
|
+
* @param arrs 二维列表
|
|
41
|
+
*
|
|
42
|
+
* @returns
|
|
43
|
+
*/
|
|
44
|
+
export declare function difference<T>(...arrs: T[][]): T[];
|
|
45
|
+
/**
|
|
46
|
+
* 返回多个集合的并集, 如果支持 union,则调用原生 union
|
|
47
|
+
*
|
|
48
|
+
* @param arrs
|
|
49
|
+
*
|
|
50
|
+
* @returns 一个包含所有给定集合的所有元素的新集合
|
|
51
|
+
*/
|
|
52
|
+
export declare function union<T>(...arrs: Set<T>[]): Set<T>;
|
|
53
|
+
export declare function union<T>(...arrs: T[][]): T[];
|
|
54
|
+
export declare function symmetricDifference<T>(...arrs: Set<T>[]): Set<T>;
|
|
55
|
+
export declare function symmetricDifference<T>(...arrs: T[][]): T[];
|
|
56
|
+
/**
|
|
57
|
+
* 返回一个布尔值,指示此集合中的所有元素是否都在给定的集合中。
|
|
58
|
+
* @param a1
|
|
59
|
+
* @param a2
|
|
60
|
+
* @returns
|
|
61
|
+
*/
|
|
62
|
+
export declare function isSubsetOf<T>(a1: T[] | Set<T>, a2: T[] | Set<T>): boolean;
|
|
63
|
+
/**
|
|
64
|
+
* 返回一个布尔值,指示给定集合中的所有元素是否都在此集合中。
|
|
65
|
+
* @param arr1
|
|
66
|
+
* @param arr2
|
|
67
|
+
* @returns
|
|
68
|
+
*/
|
|
69
|
+
export declare function isSupersetOf<T>(arr1: T[] | Set<T>, arr2: T[] | Set<T>): boolean;
|
|
70
|
+
/**
|
|
71
|
+
* 返回一个布尔值,指示此集合是否与给定集合没有公共元素。
|
|
72
|
+
*
|
|
73
|
+
* 判断两个集合是否有交集, 也可以通过 intersection(arr1, arr2).length 判断
|
|
74
|
+
*
|
|
75
|
+
* @param arr1
|
|
76
|
+
* @param arr2
|
|
77
|
+
* @returns
|
|
78
|
+
*/
|
|
79
|
+
export declare function isDisjointFrom<T>(arr1: T[] | Set<T>, arr2: T[] | Set<T>): boolean;
|
package/lib/src/array.js
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 数组排序
|
|
3
|
+
* @param arr 待排序数组
|
|
4
|
+
* @param order 排序信息, asc - 升序, desc - 倒序
|
|
5
|
+
* @param orderKey 如果是个对象数组,按哪个字段排序
|
|
6
|
+
* @returns
|
|
7
|
+
*/
|
|
8
|
+
export function order(arr, order = "asc", orderKey = null) {
|
|
9
|
+
const collator = new Intl.Collator(undefined, { numeric: true });
|
|
10
|
+
return arr.sort((a, b) => {
|
|
11
|
+
let aValue = a;
|
|
12
|
+
let bValue = b;
|
|
13
|
+
if (typeof a === "object" && orderKey != null) {
|
|
14
|
+
// @ts-ignore
|
|
15
|
+
aValue = a[orderKey];
|
|
16
|
+
// @ts-ignore
|
|
17
|
+
bValue = b[orderKey];
|
|
18
|
+
}
|
|
19
|
+
let aGtb = -1;
|
|
20
|
+
if (typeof aValue === "string") {
|
|
21
|
+
aGtb = collator.compare(aValue, bValue);
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
aGtb = aValue >= bValue ? 1 : -1;
|
|
25
|
+
}
|
|
26
|
+
return order === "asc" ? aGtb : -aGtb;
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* 返回所有集合交集的元素的新集合
|
|
31
|
+
*/ export function intersection(...arrs) {
|
|
32
|
+
return arrs.reduce((acc, cur) => {
|
|
33
|
+
if (cur instanceof Set) {
|
|
34
|
+
//@ts-ignore
|
|
35
|
+
if (cur.intersection != null) {
|
|
36
|
+
//@ts-ignore
|
|
37
|
+
return acc.intersection(cur);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
const res = new Set();
|
|
41
|
+
for (const value of acc) {
|
|
42
|
+
if (cur.has(value)) {
|
|
43
|
+
res.add(value);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return res;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
return acc.filter((x) => cur.includes(x));
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* 返回一个包含第一个集合中的元素但不包含后续给定集合中元素的新集合
|
|
56
|
+
* @param arrs 新集合
|
|
57
|
+
* @returns
|
|
58
|
+
*/
|
|
59
|
+
export function difference(...arrs) {
|
|
60
|
+
return arrs.reduce((acc, cur) => {
|
|
61
|
+
if (acc instanceof Set) {
|
|
62
|
+
//@ts-ignore
|
|
63
|
+
if (acc.difference != null) {
|
|
64
|
+
//@ts-ignore
|
|
65
|
+
return acc.difference(cur);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
const res = new Set();
|
|
69
|
+
for (const value of acc) {
|
|
70
|
+
if (!cur.has(value)) {
|
|
71
|
+
res.add(value);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return res;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
const res = [];
|
|
79
|
+
for (const value of acc) {
|
|
80
|
+
if (!cur.includes(value)) {
|
|
81
|
+
res.push(value);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return res;
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
export function union(...arrs) {
|
|
89
|
+
return arrs.reduce((acc, cur) => {
|
|
90
|
+
if (cur instanceof Set) {
|
|
91
|
+
//@ts-ignore
|
|
92
|
+
if (cur.union != null) {
|
|
93
|
+
//@ts-ignore
|
|
94
|
+
return acc.union(cur);
|
|
95
|
+
}
|
|
96
|
+
return new Set([...acc, ...cur]);
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
return [...acc, ...cur];
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* 对称差: 返回一个包含此集合或给定集合中的元素的新集合,但不包含同时存在于这两个集合中的元素。
|
|
105
|
+
* @param arrs
|
|
106
|
+
* @returns
|
|
107
|
+
*/
|
|
108
|
+
export function symmetricDifference(...arrs) {
|
|
109
|
+
return arrs.reduce((acc, cur) => {
|
|
110
|
+
if (cur instanceof Set) {
|
|
111
|
+
//@ts-ignore
|
|
112
|
+
if (cur.symmetricDifference != null) {
|
|
113
|
+
//@ts-ignore
|
|
114
|
+
return acc.symmetricDifference(cur);
|
|
115
|
+
}
|
|
116
|
+
const res = new Set();
|
|
117
|
+
for (const item of acc) {
|
|
118
|
+
if (!cur.has(item)) {
|
|
119
|
+
res.add(item);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
for (const item of cur) {
|
|
123
|
+
if (!acc.has(item)) {
|
|
124
|
+
res.add(item);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return res;
|
|
128
|
+
}
|
|
129
|
+
const res = [];
|
|
130
|
+
for (const item of acc) {
|
|
131
|
+
if (!cur.includes(item)) {
|
|
132
|
+
res.push(item);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
for (const item of cur) {
|
|
136
|
+
if (!acc.includes(item)) {
|
|
137
|
+
res.push(item);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return res;
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* 返回一个布尔值,指示此集合中的所有元素是否都在给定的集合中。
|
|
145
|
+
* @param a1
|
|
146
|
+
* @param a2
|
|
147
|
+
* @returns
|
|
148
|
+
*/
|
|
149
|
+
export function isSubsetOf(a1, a2) {
|
|
150
|
+
//@ts-ignore
|
|
151
|
+
if (a1 instanceof Set && a1.isSubsetOf != null) {
|
|
152
|
+
//@ts-ignore
|
|
153
|
+
return a1.isSubsetOf(a2);
|
|
154
|
+
}
|
|
155
|
+
let is = true;
|
|
156
|
+
for (const item of a1) {
|
|
157
|
+
if (a2 instanceof Set) {
|
|
158
|
+
if (!a2.has(item)) {
|
|
159
|
+
is = false;
|
|
160
|
+
break;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
if (!a2.includes(item)) {
|
|
165
|
+
is = false;
|
|
166
|
+
break;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return is;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* 返回一个布尔值,指示给定集合中的所有元素是否都在此集合中。
|
|
174
|
+
* @param arr1
|
|
175
|
+
* @param arr2
|
|
176
|
+
* @returns
|
|
177
|
+
*/
|
|
178
|
+
export function isSupersetOf(arr1, arr2) {
|
|
179
|
+
return isSubsetOf(arr2, arr1);
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* 返回一个布尔值,指示此集合是否与给定集合没有公共元素。
|
|
183
|
+
*
|
|
184
|
+
* 判断两个集合是否有交集, 也可以通过 intersection(arr1, arr2).length 判断
|
|
185
|
+
*
|
|
186
|
+
* @param arr1
|
|
187
|
+
* @param arr2
|
|
188
|
+
* @returns
|
|
189
|
+
*/
|
|
190
|
+
export function isDisjointFrom(arr1, arr2) {
|
|
191
|
+
//@ts-ignore
|
|
192
|
+
if (arr1 instanceof Set && arr1.isDisjointFrom != null) {
|
|
193
|
+
//@ts-ignore
|
|
194
|
+
return arr1.isDisjointFrom(arr2);
|
|
195
|
+
}
|
|
196
|
+
let is = true;
|
|
197
|
+
for (const item of arr1) {
|
|
198
|
+
if (arr2 instanceof Set) {
|
|
199
|
+
if (arr2.has(item)) {
|
|
200
|
+
is = false;
|
|
201
|
+
break;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
if (arr2.includes(item)) {
|
|
206
|
+
is = false;
|
|
207
|
+
break;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
return is;
|
|
212
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
type RGBColorObject = {
|
|
2
|
+
r: number;
|
|
3
|
+
g: number;
|
|
4
|
+
b: number;
|
|
5
|
+
a?: number;
|
|
6
|
+
};
|
|
7
|
+
type HSVColorObject = {
|
|
8
|
+
h: number;
|
|
9
|
+
s: number;
|
|
10
|
+
v: number;
|
|
11
|
+
};
|
|
12
|
+
type ColorType = string | RGBColorObject | HSVColorObject;
|
|
13
|
+
/**
|
|
14
|
+
* 将输入的颜色值转换为RGB对象格式。
|
|
15
|
+
*
|
|
16
|
+
* @param color 可以是字符串, 也可以是一个 HSV 对象[一个包含 h、s、v 属性的对象]
|
|
17
|
+
* @returns 返回一个包含r、g、b和a(透明度)属性的RGB对象。
|
|
18
|
+
* @throws 如果输入的字符串不是有效的颜色表示,则抛出错误。
|
|
19
|
+
*/
|
|
20
|
+
export declare function toRgb(color: ColorType): RGBColorObject;
|
|
21
|
+
/**
|
|
22
|
+
* 将颜色转换为HSV颜色模型。
|
|
23
|
+
*
|
|
24
|
+
* @param color - 字符串或者RGB对象
|
|
25
|
+
* @returns 返回一个包含h、s、v属性的对象,代表HSV颜色值,其中h是色相(取值范围0到360),s是饱和度(取值范围0到1),v是明度(取值范围0到1)。
|
|
26
|
+
*/
|
|
27
|
+
export declare function toHsv(color: ColorType): HSVColorObject;
|
|
28
|
+
/**
|
|
29
|
+
* 将RGB颜色对象转换为十六进制颜色字符串。
|
|
30
|
+
* @param rgb - 包含红色(r), 绿色(g), 蓝色(b)成分的对象。
|
|
31
|
+
* @returns 返回一个表示RGB颜色的十六进制字符串,例如"#FF0000"。
|
|
32
|
+
*/
|
|
33
|
+
export declare function rgbToHex(rgb: RGBColorObject): string;
|
|
34
|
+
/**
|
|
35
|
+
* 将颜色转换为 16 进制字符串
|
|
36
|
+
* @param color - 颜色, 可以 rgb(0,0,0),rgba(0,0,0,0)字符串, 也可以是 rgb、hsv对象
|
|
37
|
+
* @returns 返回颜色的十六进制字符串,例如"#FF0000"
|
|
38
|
+
*/
|
|
39
|
+
export declare function toHex(color: ColorType): string;
|
|
40
|
+
/**
|
|
41
|
+
* 调整给定颜色深[darken]浅[lighten]
|
|
42
|
+
* @param color - 输入的颜色,可以是任意颜色表示方式
|
|
43
|
+
* @param level - 调整深浅级别, 可以是小数。默认: 1
|
|
44
|
+
* @param light - 控制调整的方向。如果为true,[lighten] 变浅,如果为false,[darken] 变深。默认: true
|
|
45
|
+
*
|
|
46
|
+
* #### 1. 颜色变浅
|
|
47
|
+
*
|
|
48
|
+
* ```
|
|
49
|
+
* adjust('#4998f4', 3, true)
|
|
50
|
+
* ```
|
|
51
|
+
*
|
|
52
|
+
* @returns 返回调整后颜色的十六进制字符串表示。
|
|
53
|
+
*/
|
|
54
|
+
export declare function adjust(color: ColorType, level?: number, light?: boolean): string;
|
|
55
|
+
export {};
|
package/lib/src/color.js
ADDED
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
const hueStep = 2; // 色相阶梯
|
|
2
|
+
const saturationStep = 0.16; // 饱和度阶梯,浅色部分
|
|
3
|
+
const saturationStep2 = 0.05; // 饱和度阶梯,深色部分
|
|
4
|
+
const brightnessStep1 = 0.05; // 亮度阶梯,浅色部分
|
|
5
|
+
const brightnessStep2 = 0.15; // 亮度阶梯,深色部分
|
|
6
|
+
/* 解析: rgb(0,0,0), rgba(0,0,0,0.1) 格式的正则 */
|
|
7
|
+
const rgbRegex = /rgba?\s*\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})(?:\s*,\s*(\d*\.?\d+))?\s*\)/;
|
|
8
|
+
/* 匹配 16 进制颜色字符串的正则: #fff, #ffffff */
|
|
9
|
+
const hexRegex = /^#(?:([0-9A-Fa-f]{2})([0-9A-Fa-f]{2})([0-9A-Fa-f]{2})|([0-9A-Fa-f]{1})([0-9A-Fa-f]{1})([0-9A-Fa-f]{1}))$/;
|
|
10
|
+
function isRgb(color) {
|
|
11
|
+
return color.r != null && color.g != null && color.b != null;
|
|
12
|
+
}
|
|
13
|
+
function isHsv(color) {
|
|
14
|
+
return color.h != null && color.s != null && color.v != null;
|
|
15
|
+
}
|
|
16
|
+
function parseRgbString(color) {
|
|
17
|
+
let colorValue = color.match(rgbRegex);
|
|
18
|
+
if (colorValue != null) {
|
|
19
|
+
const r = parseInt(colorValue[1].trim());
|
|
20
|
+
const g = parseInt(colorValue[2].trim());
|
|
21
|
+
const b = parseInt(colorValue[3].trim());
|
|
22
|
+
// 检查RGB值是否为NaN
|
|
23
|
+
if (isNaN(r) || isNaN(g) || isNaN(b)) {
|
|
24
|
+
throw new Error("Invalid RGB color.");
|
|
25
|
+
}
|
|
26
|
+
let a = 1;
|
|
27
|
+
// 如果是RGBA,解析透明度值
|
|
28
|
+
if (colorValue[4] != null) {
|
|
29
|
+
a = parseFloat(colorValue[4].trim());
|
|
30
|
+
if (isNaN(a)) {
|
|
31
|
+
a = 1;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
r,
|
|
36
|
+
g,
|
|
37
|
+
b,
|
|
38
|
+
a,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function parseHexString(color) {
|
|
43
|
+
const colorMatch = color.match(hexRegex);
|
|
44
|
+
if (colorMatch != null) {
|
|
45
|
+
// 判断是否是缩写形式的颜色(3个字符)
|
|
46
|
+
const isShortForm = colorMatch[4] !== undefined;
|
|
47
|
+
const r = parseInt(isShortForm ? colorMatch[4] + colorMatch[4] : colorMatch[1], 16);
|
|
48
|
+
const g = parseInt(isShortForm ? colorMatch[5] + colorMatch[5] : colorMatch[2], 16);
|
|
49
|
+
const b = parseInt(isShortForm ? colorMatch[6] + colorMatch[6] : colorMatch[3], 16);
|
|
50
|
+
return {
|
|
51
|
+
r,
|
|
52
|
+
g,
|
|
53
|
+
b,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* 将输入的颜色值转换为RGB对象格式。
|
|
59
|
+
*
|
|
60
|
+
* @param color 可以是字符串, 也可以是一个 HSV 对象[一个包含 h、s、v 属性的对象]
|
|
61
|
+
* @returns 返回一个包含r、g、b和a(透明度)属性的RGB对象。
|
|
62
|
+
* @throws 如果输入的字符串不是有效的颜色表示,则抛出错误。
|
|
63
|
+
*/
|
|
64
|
+
export function toRgb(color) {
|
|
65
|
+
if (typeof color === "string") {
|
|
66
|
+
let rgb = parseHexString(color);
|
|
67
|
+
if (rgb == null) {
|
|
68
|
+
rgb = parseRgbString(color);
|
|
69
|
+
}
|
|
70
|
+
if (rgb != null) {
|
|
71
|
+
return rgb;
|
|
72
|
+
}
|
|
73
|
+
throw new Error("Invalid color string");
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
// 处理RGB对象输入
|
|
77
|
+
if (isRgb(color)) {
|
|
78
|
+
return color;
|
|
79
|
+
}
|
|
80
|
+
else if (isHsv(color)) {
|
|
81
|
+
return hsvToRgb(color);
|
|
82
|
+
}
|
|
83
|
+
throw new Error("Invalid color");
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* 将颜色转换为HSV颜色模型。
|
|
88
|
+
*
|
|
89
|
+
* @param color - 字符串或者RGB对象
|
|
90
|
+
* @returns 返回一个包含h、s、v属性的对象,代表HSV颜色值,其中h是色相(取值范围0到360),s是饱和度(取值范围0到1),v是明度(取值范围0到1)。
|
|
91
|
+
*/
|
|
92
|
+
export function toHsv(color) {
|
|
93
|
+
if (isHsv(color))
|
|
94
|
+
return color;
|
|
95
|
+
const rgbColor = toRgb(color);
|
|
96
|
+
// 将RGB值标准化到0到1的范围
|
|
97
|
+
const r = rgbColor.r / 255;
|
|
98
|
+
const g = rgbColor.g / 255;
|
|
99
|
+
const b = rgbColor.b / 255;
|
|
100
|
+
// 获取最大和最小值,计算色彩的明度(V)
|
|
101
|
+
let max = Math.max(r, g, b);
|
|
102
|
+
let min = Math.min(r, g, b);
|
|
103
|
+
let delta = max - min;
|
|
104
|
+
let v = max;
|
|
105
|
+
// 计算饱和度(S)
|
|
106
|
+
let s = max === 0 ? 0 : delta / max;
|
|
107
|
+
// 计算色相(H)
|
|
108
|
+
let h = 0;
|
|
109
|
+
if (max === min) {
|
|
110
|
+
h = 0; // achromatic (no hue)
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
// 根据最大值和最小值的不同,计算色相
|
|
114
|
+
switch (max) {
|
|
115
|
+
case r:
|
|
116
|
+
h = ((g - b) / delta + (g < b ? 6 : 0)) / 6;
|
|
117
|
+
break;
|
|
118
|
+
case g:
|
|
119
|
+
h = ((b - r) / delta + 2) / 6;
|
|
120
|
+
break;
|
|
121
|
+
case b:
|
|
122
|
+
h = ((r - g) / delta + 4) / 6;
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// 将色相值乘以360,转换为度数
|
|
127
|
+
h = h * 360;
|
|
128
|
+
return { h, s, v };
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* 将HSV颜色模型转换为RGB颜色模型。
|
|
132
|
+
* @param hsv 包含色相(h)、饱和度(s)和明度(v)的对象。s 和 v 可以是 0~1之间的小数, 也可以是 0~100 直接的整数, 推荐为小数,结果更精准
|
|
133
|
+
* @returns 返回一个包含红色(r)、绿色(g)和蓝色(b)值的对象,范围为0-255。
|
|
134
|
+
*/
|
|
135
|
+
function hsvToRgb(hsv) {
|
|
136
|
+
// 将百分比形式的饱和度和明度转换为0-1的数值
|
|
137
|
+
let s = hsv.s;
|
|
138
|
+
let v = hsv.v;
|
|
139
|
+
if (s > 1) {
|
|
140
|
+
s /= 100;
|
|
141
|
+
}
|
|
142
|
+
if (v > 1) {
|
|
143
|
+
v /= 100;
|
|
144
|
+
}
|
|
145
|
+
const h = hsv.h;
|
|
146
|
+
// 根据色相值计算色相角,并计算出六个区域中的位置
|
|
147
|
+
var hi = Math.floor(h / 60) % 6;
|
|
148
|
+
var f = h / 60 - Math.floor(h / 60);
|
|
149
|
+
var p = v * (1 - s);
|
|
150
|
+
var q = v * (1 - f * s);
|
|
151
|
+
var t = v * (1 - (1 - f) * s);
|
|
152
|
+
// 根据色相角确定RGB值的具体计算
|
|
153
|
+
let r = 0, g = 0, b = 0;
|
|
154
|
+
switch (hi) {
|
|
155
|
+
case 0:
|
|
156
|
+
r = v;
|
|
157
|
+
g = t;
|
|
158
|
+
b = p;
|
|
159
|
+
break;
|
|
160
|
+
case 1:
|
|
161
|
+
r = q;
|
|
162
|
+
g = v;
|
|
163
|
+
b = p;
|
|
164
|
+
break;
|
|
165
|
+
case 2:
|
|
166
|
+
r = p;
|
|
167
|
+
g = v;
|
|
168
|
+
b = t;
|
|
169
|
+
break;
|
|
170
|
+
case 3:
|
|
171
|
+
r = p;
|
|
172
|
+
g = q;
|
|
173
|
+
b = v;
|
|
174
|
+
break;
|
|
175
|
+
case 4:
|
|
176
|
+
r = t;
|
|
177
|
+
g = p;
|
|
178
|
+
b = v;
|
|
179
|
+
break;
|
|
180
|
+
case 5:
|
|
181
|
+
r = v;
|
|
182
|
+
g = p;
|
|
183
|
+
b = q;
|
|
184
|
+
break;
|
|
185
|
+
}
|
|
186
|
+
// 将计算得到的RGB值从0-1范围转换为0-255范围
|
|
187
|
+
r = Math.round(r * 255);
|
|
188
|
+
g = Math.round(g * 255);
|
|
189
|
+
b = Math.round(b * 255);
|
|
190
|
+
return { r, g, b };
|
|
191
|
+
}
|
|
192
|
+
function getHue(hsv, i, light) {
|
|
193
|
+
let hue;
|
|
194
|
+
// 根据色相不同,色相转向不同
|
|
195
|
+
if (Math.round(hsv.h) >= 60 && Math.round(hsv.h) <= 240) {
|
|
196
|
+
hue = light
|
|
197
|
+
? Math.round(hsv.h) - hueStep * i
|
|
198
|
+
: Math.round(hsv.h) + hueStep * i;
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
hue = light
|
|
202
|
+
? Math.round(hsv.h) + hueStep * i
|
|
203
|
+
: Math.round(hsv.h) - hueStep * i;
|
|
204
|
+
}
|
|
205
|
+
if (hue < 0) {
|
|
206
|
+
hue += 360;
|
|
207
|
+
}
|
|
208
|
+
else if (hue >= 360) {
|
|
209
|
+
hue -= 360;
|
|
210
|
+
}
|
|
211
|
+
return hue;
|
|
212
|
+
}
|
|
213
|
+
function getSaturation(hsv, i, light) {
|
|
214
|
+
// grey color don't change saturation
|
|
215
|
+
if (hsv.h === 0 && hsv.s === 0) {
|
|
216
|
+
return hsv.s;
|
|
217
|
+
}
|
|
218
|
+
let saturation;
|
|
219
|
+
if (light) {
|
|
220
|
+
saturation = hsv.s - saturationStep * i;
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
saturation = hsv.s + saturationStep2 * i;
|
|
224
|
+
}
|
|
225
|
+
// 边界值修正
|
|
226
|
+
if (saturation > 1) {
|
|
227
|
+
saturation = 1;
|
|
228
|
+
}
|
|
229
|
+
if (saturation < 0.06) {
|
|
230
|
+
saturation = 0.06;
|
|
231
|
+
}
|
|
232
|
+
return Number(saturation.toFixed(2));
|
|
233
|
+
}
|
|
234
|
+
function getValue(hsv, i, light) {
|
|
235
|
+
let value;
|
|
236
|
+
if (light) {
|
|
237
|
+
value = hsv.v + brightnessStep1 * i;
|
|
238
|
+
}
|
|
239
|
+
else {
|
|
240
|
+
value = hsv.v - brightnessStep2 * i;
|
|
241
|
+
}
|
|
242
|
+
if (value > 1) {
|
|
243
|
+
value = 1;
|
|
244
|
+
}
|
|
245
|
+
return Number(value.toFixed(2));
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* 将RGB颜色对象转换为十六进制颜色字符串。
|
|
249
|
+
* @param rgb - 包含红色(r), 绿色(g), 蓝色(b)成分的对象。
|
|
250
|
+
* @returns 返回一个表示RGB颜色的十六进制字符串,例如"#FF0000"。
|
|
251
|
+
*/
|
|
252
|
+
export function rgbToHex(rgb) {
|
|
253
|
+
// 将一个数字转换为两位数的十六进制字符串
|
|
254
|
+
const toHex = (n) => n.toString(16).padStart(2, "0");
|
|
255
|
+
// 将RGB颜色值转换为十六进制字符串并大写化
|
|
256
|
+
return `#${toHex(rgb.r)}${toHex(rgb.g)}${toHex(rgb.b)}`.toUpperCase();
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* 将颜色转换为 16 进制字符串
|
|
260
|
+
* @param color - 颜色, 可以 rgb(0,0,0),rgba(0,0,0,0)字符串, 也可以是 rgb、hsv对象
|
|
261
|
+
* @returns 返回颜色的十六进制字符串,例如"#FF0000"
|
|
262
|
+
*/
|
|
263
|
+
export function toHex(color) {
|
|
264
|
+
if (typeof color === "string") {
|
|
265
|
+
if (hexRegex.test(color)) {
|
|
266
|
+
return color;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
return rgbToHex(toRgb(color));
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* 调整给定颜色深[darken]浅[lighten]
|
|
273
|
+
* @param color - 输入的颜色,可以是任意颜色表示方式
|
|
274
|
+
* @param level - 调整深浅级别, 可以是小数。默认: 1
|
|
275
|
+
* @param light - 控制调整的方向。如果为true,[lighten] 变浅,如果为false,[darken] 变深。默认: true
|
|
276
|
+
*
|
|
277
|
+
* #### 1. 颜色变浅
|
|
278
|
+
*
|
|
279
|
+
* ```
|
|
280
|
+
* adjust('#4998f4', 3, true)
|
|
281
|
+
* ```
|
|
282
|
+
*
|
|
283
|
+
* @returns 返回调整后颜色的十六进制字符串表示。
|
|
284
|
+
*/
|
|
285
|
+
export function adjust(color, level = 1, light = true) {
|
|
286
|
+
// 将输入的颜色转换为HSV格式
|
|
287
|
+
const hsv = toHsv(color);
|
|
288
|
+
// 根据level和light参数调整颜色的H、S、V值,并转换回十六进制颜色表示
|
|
289
|
+
return toHex({
|
|
290
|
+
h: getHue(hsv, level, light),
|
|
291
|
+
s: getSaturation(hsv, level, light),
|
|
292
|
+
v: getValue(hsv, level, light),
|
|
293
|
+
});
|
|
294
|
+
}
|