@hzab/utils 1.1.1 → 1.1.3
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/changelog.md +8 -54
- package/package.json +1 -1
- package/src/array.ts +8 -8
- package/src/base64Str.ts +49 -49
- package/src/blob.ts +42 -42
- package/src/color.ts +302 -302
- package/src/empty-val.ts +40 -40
- package/src/file/file.ts +37 -37
- package/src/file/fileName.ts +98 -98
- package/src/formily/cloneSchema.ts +63 -63
- package/src/formily/global-components.ts +48 -48
- package/src/formily/schema-merge.ts +68 -68
- package/src/locationUtils.ts +26 -26
- package/src/options.ts +226 -226
- package/src/string.ts +31 -31
- package/src/upload/OfflineUpload.ts +342 -341
- package/src/upload/fileDataNormalization.ts +281 -281
- package/src/upload/ossUpload.ts +23 -22
- package/src/upload/uploadUtils.ts +112 -42
package/src/color.ts
CHANGED
|
@@ -1,302 +1,302 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 计算颜色的亮度
|
|
3
|
-
* @param r
|
|
4
|
-
* @param g
|
|
5
|
-
* @param b
|
|
6
|
-
* @returns
|
|
7
|
-
*/
|
|
8
|
-
export function luminance(r, g, b) {
|
|
9
|
-
const a = [r, g, b].map((v) => {
|
|
10
|
-
v /= 255;
|
|
11
|
-
return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
|
|
12
|
-
});
|
|
13
|
-
return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* 计算两个颜色之间的对比度
|
|
18
|
-
* @param l1
|
|
19
|
-
* @param l2
|
|
20
|
-
* @returns
|
|
21
|
-
*/
|
|
22
|
-
export function contrast(l1, l2) {
|
|
23
|
-
const brightest = Math.max(l1, l2);
|
|
24
|
-
const darkest = Math.min(l1, l2);
|
|
25
|
-
return (brightest + 0.05) / (darkest + 0.05);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* 计算对比度
|
|
30
|
-
* @param luminance1
|
|
31
|
-
* @param luminance2
|
|
32
|
-
* @returns
|
|
33
|
-
*/
|
|
34
|
-
export function contrastRatio(luminance1, luminance2) {
|
|
35
|
-
return (Math.max(luminance1, luminance2) + 0.05) / (Math.min(luminance1, luminance2) + 0.05);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* 十六进制颜色转 RGB
|
|
40
|
-
* @param hex
|
|
41
|
-
* @returns
|
|
42
|
-
*/
|
|
43
|
-
export function hexToRGB(hex) {
|
|
44
|
-
hex = hex.replace("#", "");
|
|
45
|
-
if (hex.length === 3) {
|
|
46
|
-
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
|
|
47
|
-
}
|
|
48
|
-
const r = parseInt(hex.substring(0, 2), 16);
|
|
49
|
-
const g = parseInt(hex.substring(2, 4), 16);
|
|
50
|
-
const b = parseInt(hex.substring(4, 6), 16);
|
|
51
|
-
return [r, g, b];
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* rgb 数值限制
|
|
56
|
-
* @param val
|
|
57
|
-
* @returns
|
|
58
|
-
*/
|
|
59
|
-
export function rgbNumLimit(val) {
|
|
60
|
-
if (val > 250) {
|
|
61
|
-
return 250;
|
|
62
|
-
}
|
|
63
|
-
if (val < 0) {
|
|
64
|
-
return 0;
|
|
65
|
-
}
|
|
66
|
-
return val;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* RGB 转十六进制颜色
|
|
71
|
-
* @param r
|
|
72
|
-
* @param g
|
|
73
|
-
* @param b
|
|
74
|
-
* @returns
|
|
75
|
-
*/
|
|
76
|
-
export function rgbToHex(r, g, b) {
|
|
77
|
-
return (
|
|
78
|
-
"#" +
|
|
79
|
-
[r, g, b]
|
|
80
|
-
.map((x) => {
|
|
81
|
-
const hex = x.toString(16);
|
|
82
|
-
return hex.length === 1 ? "0" + hex : hex;
|
|
83
|
-
})
|
|
84
|
-
.join("")
|
|
85
|
-
);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* RGB 转 HSL
|
|
90
|
-
* @param r
|
|
91
|
-
* @param g
|
|
92
|
-
* @param b
|
|
93
|
-
* @returns
|
|
94
|
-
*/
|
|
95
|
-
export function rgbToHsl(r, g, b) {
|
|
96
|
-
r /= 255;
|
|
97
|
-
g /= 255;
|
|
98
|
-
b /= 255;
|
|
99
|
-
const max = Math.max(r, g, b);
|
|
100
|
-
const min = Math.min(r, g, b);
|
|
101
|
-
let h,
|
|
102
|
-
s,
|
|
103
|
-
l = (max + min) / 2;
|
|
104
|
-
|
|
105
|
-
if (max === min) {
|
|
106
|
-
h = s = 0;
|
|
107
|
-
} else {
|
|
108
|
-
const d = max - min;
|
|
109
|
-
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
110
|
-
switch (max) {
|
|
111
|
-
case r:
|
|
112
|
-
h = (g - b) / d + (g < b ? 6 : 0);
|
|
113
|
-
break;
|
|
114
|
-
case g:
|
|
115
|
-
h = (b - r) / d + 2;
|
|
116
|
-
break;
|
|
117
|
-
case b:
|
|
118
|
-
h = (r - g) / d + 4;
|
|
119
|
-
break;
|
|
120
|
-
}
|
|
121
|
-
h /= 6;
|
|
122
|
-
}
|
|
123
|
-
return [h * 360, s * 100, l * 100];
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* HSL 转 RGB
|
|
128
|
-
* @param h
|
|
129
|
-
* @param s
|
|
130
|
-
* @param l
|
|
131
|
-
* @returns
|
|
132
|
-
*/
|
|
133
|
-
export function hslToRgb(h, s, l) {
|
|
134
|
-
h /= 360;
|
|
135
|
-
s /= 100;
|
|
136
|
-
l /= 100;
|
|
137
|
-
let r, g, b;
|
|
138
|
-
|
|
139
|
-
if (s === 0) {
|
|
140
|
-
r = g = b = l;
|
|
141
|
-
} else {
|
|
142
|
-
const hue2rgb = (p, q, t) => {
|
|
143
|
-
if (t < 0) t += 1;
|
|
144
|
-
if (t > 1) t -= 1;
|
|
145
|
-
if (t < 1 / 6) return p + (q - p) * 6 * t;
|
|
146
|
-
if (t < 1 / 2) return q;
|
|
147
|
-
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
|
|
148
|
-
return p;
|
|
149
|
-
};
|
|
150
|
-
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
|
151
|
-
const p = 2 * l - q;
|
|
152
|
-
r = hue2rgb(p, q, h + 1 / 3);
|
|
153
|
-
g = hue2rgb(p, q, h);
|
|
154
|
-
b = hue2rgb(p, q, h - 1 / 3);
|
|
155
|
-
}
|
|
156
|
-
return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* 判断是否为灰色背景
|
|
161
|
-
* @param r
|
|
162
|
-
* @param g
|
|
163
|
-
* @param b
|
|
164
|
-
* @returns
|
|
165
|
-
*/
|
|
166
|
-
export function isGray(r, g, b, opt = { tolerance: 10 }) {
|
|
167
|
-
const {
|
|
168
|
-
/**
|
|
169
|
-
* 允许的误差范围
|
|
170
|
-
*/
|
|
171
|
-
tolerance = 10,
|
|
172
|
-
} = opt || {}; //
|
|
173
|
-
return Math.abs(r - g) <= tolerance && Math.abs(g - b) <= tolerance && Math.abs(r - b) <= tolerance;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* 根据背景颜色选择合适的文本颜色(十六进制格式)
|
|
178
|
-
* @param backgroundColor
|
|
179
|
-
* @returns
|
|
180
|
-
*/
|
|
181
|
-
export function getTextColor(backgroundColor) {
|
|
182
|
-
let [r, g, b] = [0, 0, 0];
|
|
183
|
-
if (backgroundColor.startsWith("#")) {
|
|
184
|
-
[r, g, b] = hexToRGB(backgroundColor);
|
|
185
|
-
} else {
|
|
186
|
-
const div = document.createElement("div");
|
|
187
|
-
div.style.color = backgroundColor;
|
|
188
|
-
document.body.appendChild(div);
|
|
189
|
-
const cs = getComputedStyle(div);
|
|
190
|
-
const rgb = cs.color.match(/\d+/g).map(Number);
|
|
191
|
-
document.body.removeChild(div);
|
|
192
|
-
[r, g, b] = rgb;
|
|
193
|
-
}
|
|
194
|
-
const bgLuminance = luminance(r, g, b);
|
|
195
|
-
const whiteLuminance = luminance(255, 255, 255);
|
|
196
|
-
const blackLuminance = luminance(0, 0, 0);
|
|
197
|
-
const whiteContrast = contrast(bgLuminance, whiteLuminance);
|
|
198
|
-
const blackContrast = contrast(bgLuminance, blackLuminance);
|
|
199
|
-
return whiteContrast > blackContrast ? "#ffffff" : "#000000";
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
/**
|
|
203
|
-
* 根据背景亮度调整文字颜色深浅
|
|
204
|
-
* @param bgR
|
|
205
|
-
* @param bgG
|
|
206
|
-
* @param bgB
|
|
207
|
-
* @returns
|
|
208
|
-
*/
|
|
209
|
-
export function adjustTextColor(hexColor) {
|
|
210
|
-
const [bgR, bgG, bgB] = hexToRGB(hexColor);
|
|
211
|
-
const bgLuminance = luminance(bgR, bgG, bgB);
|
|
212
|
-
let textR, textG, textB;
|
|
213
|
-
const targetContrast = 4.5; // WCAG AA 标准
|
|
214
|
-
|
|
215
|
-
if (bgR === 0 && bgG === 0 && bgB === 0) {
|
|
216
|
-
// 黑色背景
|
|
217
|
-
let textR = 255,
|
|
218
|
-
textG = 255,
|
|
219
|
-
textB = 255;
|
|
220
|
-
let textLuminance = luminance(textR, textG, textB);
|
|
221
|
-
let ratio = contrastRatio(bgLuminance, textLuminance);
|
|
222
|
-
if (ratio < targetContrast) {
|
|
223
|
-
textR = 230;
|
|
224
|
-
textG = 230;
|
|
225
|
-
textB = 230;
|
|
226
|
-
}
|
|
227
|
-
return rgbToHex(textR, textG, textB);
|
|
228
|
-
} else if (bgR === 255 && bgG === 255 && bgB === 255) {
|
|
229
|
-
// 白色背景
|
|
230
|
-
let textR = 0,
|
|
231
|
-
textG = 0,
|
|
232
|
-
textB = 0;
|
|
233
|
-
let textLuminance = luminance(textR, textG, textB);
|
|
234
|
-
let ratio = contrastRatio(bgLuminance, textLuminance);
|
|
235
|
-
if (ratio < targetContrast) {
|
|
236
|
-
textR = 20;
|
|
237
|
-
textG = 20;
|
|
238
|
-
textB = 20;
|
|
239
|
-
}
|
|
240
|
-
return rgbToHex(textR, textG, textB);
|
|
241
|
-
} else if (isGray(bgR, bgG, bgB)) {
|
|
242
|
-
// 灰色背景
|
|
243
|
-
if (bgLuminance < 0.4) {
|
|
244
|
-
// 深色灰色背景,使用白色文字
|
|
245
|
-
let textR = 255,
|
|
246
|
-
textG = 255,
|
|
247
|
-
textB = 255;
|
|
248
|
-
let textLuminance = luminance(textR, textG, textB);
|
|
249
|
-
let ratio = contrastRatio(bgLuminance, textLuminance);
|
|
250
|
-
if (ratio < targetContrast) {
|
|
251
|
-
textR = 230;
|
|
252
|
-
textG = 230;
|
|
253
|
-
textB = 230;
|
|
254
|
-
}
|
|
255
|
-
return rgbToHex(textR, textG, textB);
|
|
256
|
-
} else {
|
|
257
|
-
// 浅色灰色背景,使用黑色文字
|
|
258
|
-
let textR = 0,
|
|
259
|
-
textG = 0,
|
|
260
|
-
textB = 0;
|
|
261
|
-
let textLuminance = luminance(textR, textG, textB);
|
|
262
|
-
let ratio = contrastRatio(bgLuminance, textLuminance);
|
|
263
|
-
if (ratio < targetContrast) {
|
|
264
|
-
textR = 20;
|
|
265
|
-
textG = 20;
|
|
266
|
-
textB = 20;
|
|
267
|
-
}
|
|
268
|
-
return rgbToHex(textR, textG, textB);
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
// 非黑白灰背景,使用差值颜色
|
|
273
|
-
const adjustNum = 150;
|
|
274
|
-
if (bgLuminance > 0.5) {
|
|
275
|
-
// 背景较亮,文字颜色调深
|
|
276
|
-
textR = Math.max(0, bgR - adjustNum);
|
|
277
|
-
textG = Math.max(0, bgG - adjustNum);
|
|
278
|
-
textB = Math.max(0, bgB - adjustNum);
|
|
279
|
-
} else {
|
|
280
|
-
// 背景较暗,文字颜色调亮
|
|
281
|
-
textR = Math.min(255, bgR + adjustNum);
|
|
282
|
-
textG = Math.min(255, bgG + adjustNum);
|
|
283
|
-
textB = Math.min(255, bgB + adjustNum);
|
|
284
|
-
}
|
|
285
|
-
return rgbToHex(textR, textG, textB);
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
/**
|
|
289
|
-
* 调整颜色深浅
|
|
290
|
-
* @param hexColor
|
|
291
|
-
* @param amount
|
|
292
|
-
* @returns
|
|
293
|
-
*/
|
|
294
|
-
export function adjustColor(hexColor, amount) {
|
|
295
|
-
const [r, g, b] = hexToRGB(hexColor);
|
|
296
|
-
|
|
297
|
-
const newR = rgbNumLimit(r + amount);
|
|
298
|
-
const newG = rgbNumLimit(g + amount);
|
|
299
|
-
const newB = rgbNumLimit(b + amount);
|
|
300
|
-
|
|
301
|
-
return rgbToHex(newR, newG, newB);
|
|
302
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* 计算颜色的亮度
|
|
3
|
+
* @param r
|
|
4
|
+
* @param g
|
|
5
|
+
* @param b
|
|
6
|
+
* @returns
|
|
7
|
+
*/
|
|
8
|
+
export function luminance(r, g, b) {
|
|
9
|
+
const a = [r, g, b].map((v) => {
|
|
10
|
+
v /= 255;
|
|
11
|
+
return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
|
|
12
|
+
});
|
|
13
|
+
return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* 计算两个颜色之间的对比度
|
|
18
|
+
* @param l1
|
|
19
|
+
* @param l2
|
|
20
|
+
* @returns
|
|
21
|
+
*/
|
|
22
|
+
export function contrast(l1, l2) {
|
|
23
|
+
const brightest = Math.max(l1, l2);
|
|
24
|
+
const darkest = Math.min(l1, l2);
|
|
25
|
+
return (brightest + 0.05) / (darkest + 0.05);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* 计算对比度
|
|
30
|
+
* @param luminance1
|
|
31
|
+
* @param luminance2
|
|
32
|
+
* @returns
|
|
33
|
+
*/
|
|
34
|
+
export function contrastRatio(luminance1, luminance2) {
|
|
35
|
+
return (Math.max(luminance1, luminance2) + 0.05) / (Math.min(luminance1, luminance2) + 0.05);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* 十六进制颜色转 RGB
|
|
40
|
+
* @param hex
|
|
41
|
+
* @returns
|
|
42
|
+
*/
|
|
43
|
+
export function hexToRGB(hex) {
|
|
44
|
+
hex = hex.replace("#", "");
|
|
45
|
+
if (hex.length === 3) {
|
|
46
|
+
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
|
|
47
|
+
}
|
|
48
|
+
const r = parseInt(hex.substring(0, 2), 16);
|
|
49
|
+
const g = parseInt(hex.substring(2, 4), 16);
|
|
50
|
+
const b = parseInt(hex.substring(4, 6), 16);
|
|
51
|
+
return [r, g, b];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* rgb 数值限制
|
|
56
|
+
* @param val
|
|
57
|
+
* @returns
|
|
58
|
+
*/
|
|
59
|
+
export function rgbNumLimit(val) {
|
|
60
|
+
if (val > 250) {
|
|
61
|
+
return 250;
|
|
62
|
+
}
|
|
63
|
+
if (val < 0) {
|
|
64
|
+
return 0;
|
|
65
|
+
}
|
|
66
|
+
return val;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* RGB 转十六进制颜色
|
|
71
|
+
* @param r
|
|
72
|
+
* @param g
|
|
73
|
+
* @param b
|
|
74
|
+
* @returns
|
|
75
|
+
*/
|
|
76
|
+
export function rgbToHex(r, g, b) {
|
|
77
|
+
return (
|
|
78
|
+
"#" +
|
|
79
|
+
[r, g, b]
|
|
80
|
+
.map((x) => {
|
|
81
|
+
const hex = x.toString(16);
|
|
82
|
+
return hex.length === 1 ? "0" + hex : hex;
|
|
83
|
+
})
|
|
84
|
+
.join("")
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* RGB 转 HSL
|
|
90
|
+
* @param r
|
|
91
|
+
* @param g
|
|
92
|
+
* @param b
|
|
93
|
+
* @returns
|
|
94
|
+
*/
|
|
95
|
+
export function rgbToHsl(r, g, b) {
|
|
96
|
+
r /= 255;
|
|
97
|
+
g /= 255;
|
|
98
|
+
b /= 255;
|
|
99
|
+
const max = Math.max(r, g, b);
|
|
100
|
+
const min = Math.min(r, g, b);
|
|
101
|
+
let h,
|
|
102
|
+
s,
|
|
103
|
+
l = (max + min) / 2;
|
|
104
|
+
|
|
105
|
+
if (max === min) {
|
|
106
|
+
h = s = 0;
|
|
107
|
+
} else {
|
|
108
|
+
const d = max - min;
|
|
109
|
+
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
110
|
+
switch (max) {
|
|
111
|
+
case r:
|
|
112
|
+
h = (g - b) / d + (g < b ? 6 : 0);
|
|
113
|
+
break;
|
|
114
|
+
case g:
|
|
115
|
+
h = (b - r) / d + 2;
|
|
116
|
+
break;
|
|
117
|
+
case b:
|
|
118
|
+
h = (r - g) / d + 4;
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
h /= 6;
|
|
122
|
+
}
|
|
123
|
+
return [h * 360, s * 100, l * 100];
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* HSL 转 RGB
|
|
128
|
+
* @param h
|
|
129
|
+
* @param s
|
|
130
|
+
* @param l
|
|
131
|
+
* @returns
|
|
132
|
+
*/
|
|
133
|
+
export function hslToRgb(h, s, l) {
|
|
134
|
+
h /= 360;
|
|
135
|
+
s /= 100;
|
|
136
|
+
l /= 100;
|
|
137
|
+
let r, g, b;
|
|
138
|
+
|
|
139
|
+
if (s === 0) {
|
|
140
|
+
r = g = b = l;
|
|
141
|
+
} else {
|
|
142
|
+
const hue2rgb = (p, q, t) => {
|
|
143
|
+
if (t < 0) t += 1;
|
|
144
|
+
if (t > 1) t -= 1;
|
|
145
|
+
if (t < 1 / 6) return p + (q - p) * 6 * t;
|
|
146
|
+
if (t < 1 / 2) return q;
|
|
147
|
+
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
|
|
148
|
+
return p;
|
|
149
|
+
};
|
|
150
|
+
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
|
151
|
+
const p = 2 * l - q;
|
|
152
|
+
r = hue2rgb(p, q, h + 1 / 3);
|
|
153
|
+
g = hue2rgb(p, q, h);
|
|
154
|
+
b = hue2rgb(p, q, h - 1 / 3);
|
|
155
|
+
}
|
|
156
|
+
return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* 判断是否为灰色背景
|
|
161
|
+
* @param r
|
|
162
|
+
* @param g
|
|
163
|
+
* @param b
|
|
164
|
+
* @returns
|
|
165
|
+
*/
|
|
166
|
+
export function isGray(r, g, b, opt = { tolerance: 10 }) {
|
|
167
|
+
const {
|
|
168
|
+
/**
|
|
169
|
+
* 允许的误差范围
|
|
170
|
+
*/
|
|
171
|
+
tolerance = 10,
|
|
172
|
+
} = opt || {}; //
|
|
173
|
+
return Math.abs(r - g) <= tolerance && Math.abs(g - b) <= tolerance && Math.abs(r - b) <= tolerance;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* 根据背景颜色选择合适的文本颜色(十六进制格式)
|
|
178
|
+
* @param backgroundColor
|
|
179
|
+
* @returns
|
|
180
|
+
*/
|
|
181
|
+
export function getTextColor(backgroundColor) {
|
|
182
|
+
let [r, g, b] = [0, 0, 0];
|
|
183
|
+
if (backgroundColor.startsWith("#")) {
|
|
184
|
+
[r, g, b] = hexToRGB(backgroundColor);
|
|
185
|
+
} else {
|
|
186
|
+
const div = document.createElement("div");
|
|
187
|
+
div.style.color = backgroundColor;
|
|
188
|
+
document.body.appendChild(div);
|
|
189
|
+
const cs = getComputedStyle(div);
|
|
190
|
+
const rgb = cs.color.match(/\d+/g).map(Number);
|
|
191
|
+
document.body.removeChild(div);
|
|
192
|
+
[r, g, b] = rgb;
|
|
193
|
+
}
|
|
194
|
+
const bgLuminance = luminance(r, g, b);
|
|
195
|
+
const whiteLuminance = luminance(255, 255, 255);
|
|
196
|
+
const blackLuminance = luminance(0, 0, 0);
|
|
197
|
+
const whiteContrast = contrast(bgLuminance, whiteLuminance);
|
|
198
|
+
const blackContrast = contrast(bgLuminance, blackLuminance);
|
|
199
|
+
return whiteContrast > blackContrast ? "#ffffff" : "#000000";
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* 根据背景亮度调整文字颜色深浅
|
|
204
|
+
* @param bgR
|
|
205
|
+
* @param bgG
|
|
206
|
+
* @param bgB
|
|
207
|
+
* @returns
|
|
208
|
+
*/
|
|
209
|
+
export function adjustTextColor(hexColor) {
|
|
210
|
+
const [bgR, bgG, bgB] = hexToRGB(hexColor);
|
|
211
|
+
const bgLuminance = luminance(bgR, bgG, bgB);
|
|
212
|
+
let textR, textG, textB;
|
|
213
|
+
const targetContrast = 4.5; // WCAG AA 标准
|
|
214
|
+
|
|
215
|
+
if (bgR === 0 && bgG === 0 && bgB === 0) {
|
|
216
|
+
// 黑色背景
|
|
217
|
+
let textR = 255,
|
|
218
|
+
textG = 255,
|
|
219
|
+
textB = 255;
|
|
220
|
+
let textLuminance = luminance(textR, textG, textB);
|
|
221
|
+
let ratio = contrastRatio(bgLuminance, textLuminance);
|
|
222
|
+
if (ratio < targetContrast) {
|
|
223
|
+
textR = 230;
|
|
224
|
+
textG = 230;
|
|
225
|
+
textB = 230;
|
|
226
|
+
}
|
|
227
|
+
return rgbToHex(textR, textG, textB);
|
|
228
|
+
} else if (bgR === 255 && bgG === 255 && bgB === 255) {
|
|
229
|
+
// 白色背景
|
|
230
|
+
let textR = 0,
|
|
231
|
+
textG = 0,
|
|
232
|
+
textB = 0;
|
|
233
|
+
let textLuminance = luminance(textR, textG, textB);
|
|
234
|
+
let ratio = contrastRatio(bgLuminance, textLuminance);
|
|
235
|
+
if (ratio < targetContrast) {
|
|
236
|
+
textR = 20;
|
|
237
|
+
textG = 20;
|
|
238
|
+
textB = 20;
|
|
239
|
+
}
|
|
240
|
+
return rgbToHex(textR, textG, textB);
|
|
241
|
+
} else if (isGray(bgR, bgG, bgB)) {
|
|
242
|
+
// 灰色背景
|
|
243
|
+
if (bgLuminance < 0.4) {
|
|
244
|
+
// 深色灰色背景,使用白色文字
|
|
245
|
+
let textR = 255,
|
|
246
|
+
textG = 255,
|
|
247
|
+
textB = 255;
|
|
248
|
+
let textLuminance = luminance(textR, textG, textB);
|
|
249
|
+
let ratio = contrastRatio(bgLuminance, textLuminance);
|
|
250
|
+
if (ratio < targetContrast) {
|
|
251
|
+
textR = 230;
|
|
252
|
+
textG = 230;
|
|
253
|
+
textB = 230;
|
|
254
|
+
}
|
|
255
|
+
return rgbToHex(textR, textG, textB);
|
|
256
|
+
} else {
|
|
257
|
+
// 浅色灰色背景,使用黑色文字
|
|
258
|
+
let textR = 0,
|
|
259
|
+
textG = 0,
|
|
260
|
+
textB = 0;
|
|
261
|
+
let textLuminance = luminance(textR, textG, textB);
|
|
262
|
+
let ratio = contrastRatio(bgLuminance, textLuminance);
|
|
263
|
+
if (ratio < targetContrast) {
|
|
264
|
+
textR = 20;
|
|
265
|
+
textG = 20;
|
|
266
|
+
textB = 20;
|
|
267
|
+
}
|
|
268
|
+
return rgbToHex(textR, textG, textB);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// 非黑白灰背景,使用差值颜色
|
|
273
|
+
const adjustNum = 150;
|
|
274
|
+
if (bgLuminance > 0.5) {
|
|
275
|
+
// 背景较亮,文字颜色调深
|
|
276
|
+
textR = Math.max(0, bgR - adjustNum);
|
|
277
|
+
textG = Math.max(0, bgG - adjustNum);
|
|
278
|
+
textB = Math.max(0, bgB - adjustNum);
|
|
279
|
+
} else {
|
|
280
|
+
// 背景较暗,文字颜色调亮
|
|
281
|
+
textR = Math.min(255, bgR + adjustNum);
|
|
282
|
+
textG = Math.min(255, bgG + adjustNum);
|
|
283
|
+
textB = Math.min(255, bgB + adjustNum);
|
|
284
|
+
}
|
|
285
|
+
return rgbToHex(textR, textG, textB);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* 调整颜色深浅
|
|
290
|
+
* @param hexColor
|
|
291
|
+
* @param amount
|
|
292
|
+
* @returns
|
|
293
|
+
*/
|
|
294
|
+
export function adjustColor(hexColor, amount) {
|
|
295
|
+
const [r, g, b] = hexToRGB(hexColor);
|
|
296
|
+
|
|
297
|
+
const newR = rgbNumLimit(r + amount);
|
|
298
|
+
const newG = rgbNumLimit(g + amount);
|
|
299
|
+
const newB = rgbNumLimit(b + amount);
|
|
300
|
+
|
|
301
|
+
return rgbToHex(newR, newG, newB);
|
|
302
|
+
}
|
package/src/empty-val.ts
CHANGED
|
@@ -1,40 +1,40 @@
|
|
|
1
|
-
export interface ICheckEmptyOpt {
|
|
2
|
-
/** 【废弃】空值占位符 */
|
|
3
|
-
emptyStr?: string;
|
|
4
|
-
/** 空值占位符 */
|
|
5
|
-
emptySymbol?: string;
|
|
6
|
-
checkEmptyArr?: boolean;
|
|
7
|
-
}
|
|
8
|
-
export interface IHandleEmptyValOpt extends ICheckEmptyOpt {}
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* 空数据判断
|
|
12
|
-
* @param {*} val
|
|
13
|
-
* @param {*} opt
|
|
14
|
-
* @returns
|
|
15
|
-
*/
|
|
16
|
-
export function checkEmpty(val, opt: ICheckEmptyOpt = {}) {
|
|
17
|
-
const { checkEmptyArr = true } = opt || {};
|
|
18
|
-
if (val === "" || val === null || val === undefined) {
|
|
19
|
-
return true;
|
|
20
|
-
}
|
|
21
|
-
if (checkEmptyArr && Array.isArray(val) && Array.length === 0) {
|
|
22
|
-
return true;
|
|
23
|
-
}
|
|
24
|
-
return false;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* 处理空数据显示占位符
|
|
29
|
-
* @param val
|
|
30
|
-
* @param opt
|
|
31
|
-
* @returns
|
|
32
|
-
*/
|
|
33
|
-
export const handleEmptyVal = (val, opt: IHandleEmptyValOpt = {}) => {
|
|
34
|
-
const { emptyStr = "--" } = opt || {};
|
|
35
|
-
const emptySymbol = opt?.emptySymbol ?? emptyStr;
|
|
36
|
-
if (checkEmpty(val, opt)) {
|
|
37
|
-
return emptySymbol;
|
|
38
|
-
}
|
|
39
|
-
return val;
|
|
40
|
-
};
|
|
1
|
+
export interface ICheckEmptyOpt {
|
|
2
|
+
/** 【废弃】空值占位符 */
|
|
3
|
+
emptyStr?: string;
|
|
4
|
+
/** 空值占位符 */
|
|
5
|
+
emptySymbol?: string;
|
|
6
|
+
checkEmptyArr?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface IHandleEmptyValOpt extends ICheckEmptyOpt {}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* 空数据判断
|
|
12
|
+
* @param {*} val
|
|
13
|
+
* @param {*} opt
|
|
14
|
+
* @returns
|
|
15
|
+
*/
|
|
16
|
+
export function checkEmpty(val, opt: ICheckEmptyOpt = {}) {
|
|
17
|
+
const { checkEmptyArr = true } = opt || {};
|
|
18
|
+
if (val === "" || val === null || val === undefined) {
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
if (checkEmptyArr && Array.isArray(val) && Array.length === 0) {
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* 处理空数据显示占位符
|
|
29
|
+
* @param val
|
|
30
|
+
* @param opt
|
|
31
|
+
* @returns
|
|
32
|
+
*/
|
|
33
|
+
export const handleEmptyVal = (val, opt: IHandleEmptyValOpt = {}) => {
|
|
34
|
+
const { emptyStr = "--" } = opt || {};
|
|
35
|
+
const emptySymbol = opt?.emptySymbol ?? emptyStr;
|
|
36
|
+
if (checkEmpty(val, opt)) {
|
|
37
|
+
return emptySymbol;
|
|
38
|
+
}
|
|
39
|
+
return val;
|
|
40
|
+
};
|