@versatiles/style 5.5.2 → 5.7.0
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/README.MD +36 -33
- package/dist/index.d.ts +539 -65
- package/dist/index.js +782 -217
- package/dist/index.js.map +1 -1
- package/package.json +26 -25
- package/src/color/abstract.ts +145 -26
- package/src/color/hsl.ts +88 -5
- package/src/color/hsv.ts +73 -5
- package/src/color/index.test.ts +0 -20
- package/src/color/index.ts +0 -3
- package/src/color/random.test.ts +21 -0
- package/src/color/rgb.test.ts +40 -72
- package/src/color/rgb.ts +152 -7
- package/src/color/utils.ts +10 -4
- package/src/guess_style/guess_style.test.ts +1 -1
- package/src/guess_style/guess_style.ts +42 -2
- package/src/index.test.ts +2 -1
- package/src/index.ts +89 -4
- package/src/shortbread/layers.ts +30 -5
- package/src/style_builder/recolor.test.ts +46 -0
- package/src/style_builder/recolor.ts +161 -34
- package/src/style_builder/style_builder.test.ts +2 -0
- package/src/style_builder/style_builder.ts +8 -9
- package/src/style_builder/types.ts +23 -58
- package/src/styles/colorful.ts +36 -7
- package/src/styles/index.ts +2 -0
- package/src/styles/shadow.ts +11 -0
package/dist/index.js
CHANGED
|
@@ -1,71 +1,188 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The abstract `Color` class provides a blueprint for color manipulation and conversion.
|
|
3
|
+
* It includes methods for converting between different color models ({@link HSL}, {@link HSV}, {@link RGB}),
|
|
4
|
+
* as well as various color transformations such as inversion, rotation, saturation, and blending.
|
|
5
|
+
*
|
|
6
|
+
* @abstract
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Abstract class representing a color.
|
|
10
|
+
*/
|
|
1
11
|
class Color {
|
|
12
|
+
/**
|
|
13
|
+
* Parses a color from a string or another Color instance.
|
|
14
|
+
* @param input - The input color as a string or Color instance.
|
|
15
|
+
* @returns The parsed Color instance.
|
|
16
|
+
*/
|
|
2
17
|
static parse;
|
|
18
|
+
/**
|
|
19
|
+
* The HSL color model.
|
|
20
|
+
*/
|
|
3
21
|
static HSL;
|
|
22
|
+
/**
|
|
23
|
+
* The HSV color model.
|
|
24
|
+
*/
|
|
4
25
|
static HSV;
|
|
26
|
+
/**
|
|
27
|
+
* The RGB color model.
|
|
28
|
+
*/
|
|
5
29
|
static RGB;
|
|
6
|
-
|
|
30
|
+
/**
|
|
31
|
+
* Converts the color to a hexadecimal string.
|
|
32
|
+
* @returns The hexadecimal representation of the color.
|
|
33
|
+
*/
|
|
7
34
|
asHex() {
|
|
8
|
-
return this.
|
|
9
|
-
}
|
|
10
|
-
toHSL() {
|
|
11
|
-
return this.asHSL();
|
|
12
|
-
}
|
|
13
|
-
toHSV() {
|
|
14
|
-
return this.asHSV();
|
|
15
|
-
}
|
|
16
|
-
toRGB() {
|
|
17
|
-
return this.asRGB();
|
|
35
|
+
return this.asRGB().asHex();
|
|
18
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* Inverts the luminosity of the color.
|
|
39
|
+
* @returns A new HSL color with inverted luminosity.
|
|
40
|
+
*/
|
|
19
41
|
invertLuminosity() {
|
|
20
|
-
return this.
|
|
42
|
+
return this.asHSL().invertLuminosity();
|
|
21
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* Rotates the hue of the color by a given offset.
|
|
46
|
+
* @param offset - The amount to rotate the hue.
|
|
47
|
+
* @returns A new HSL color with the hue rotated.
|
|
48
|
+
*/
|
|
22
49
|
rotateHue(offset) {
|
|
23
|
-
return this.
|
|
50
|
+
return this.asHSL().rotateHue(offset);
|
|
24
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* Saturates the color by a given ratio.
|
|
54
|
+
* @param ratio - The ratio to saturate the color.
|
|
55
|
+
* @returns A new HSL color with increased saturation.
|
|
56
|
+
*/
|
|
25
57
|
saturate(ratio) {
|
|
26
|
-
return this.
|
|
58
|
+
return this.asHSL().saturate(ratio);
|
|
27
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* Applies gamma correction to the color.
|
|
62
|
+
* @param value - The gamma correction value.
|
|
63
|
+
* @returns A new RGB color with gamma correction applied.
|
|
64
|
+
*/
|
|
28
65
|
gamma(value) {
|
|
29
|
-
return this.
|
|
66
|
+
return this.asRGB().gamma(value);
|
|
30
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* Inverts the color.
|
|
70
|
+
* @returns A new RGB color with inverted values.
|
|
71
|
+
*/
|
|
31
72
|
invert() {
|
|
32
|
-
return this.
|
|
73
|
+
return this.asRGB().invert();
|
|
33
74
|
}
|
|
75
|
+
/**
|
|
76
|
+
* Adjusts the contrast of the color.
|
|
77
|
+
* @param value - The contrast adjustment value.
|
|
78
|
+
* @returns A new RGB color with adjusted contrast.
|
|
79
|
+
*/
|
|
34
80
|
contrast(value) {
|
|
35
|
-
return this.
|
|
81
|
+
return this.asRGB().contrast(value);
|
|
36
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* Adjusts the brightness of the color.
|
|
85
|
+
* @param value - The brightness adjustment value.
|
|
86
|
+
* @returns A new RGB color with adjusted brightness.
|
|
87
|
+
*/
|
|
37
88
|
brightness(value) {
|
|
38
|
-
return this.
|
|
89
|
+
return this.asRGB().brightness(value);
|
|
39
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* Lightens the color by a given value.
|
|
93
|
+
* @param value - The amount to lighten the color.
|
|
94
|
+
* @returns A new RGB color that is lightened.
|
|
95
|
+
*/
|
|
40
96
|
lighten(value) {
|
|
41
|
-
return this.
|
|
97
|
+
return this.asRGB().lighten(value);
|
|
42
98
|
}
|
|
99
|
+
/**
|
|
100
|
+
* Darkens the color by a given value.
|
|
101
|
+
* @param value - The amount to darken the color.
|
|
102
|
+
* @returns A new RGB color that is darkened.
|
|
103
|
+
*/
|
|
43
104
|
darken(value) {
|
|
44
|
-
return this.
|
|
105
|
+
return this.asRGB().darken(value);
|
|
45
106
|
}
|
|
107
|
+
/**
|
|
108
|
+
* Tints the color by blending it with another color.
|
|
109
|
+
* @param value - The blend ratio.
|
|
110
|
+
* @param tintColor - The color to blend with.
|
|
111
|
+
* @returns A new RGB color that is tinted.
|
|
112
|
+
*/
|
|
46
113
|
tint(value, tintColor) {
|
|
47
|
-
return this.
|
|
114
|
+
return this.asRGB().tint(value, tintColor);
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Blends the color with another color.
|
|
118
|
+
* @param value - The blend ratio.
|
|
119
|
+
* @param blendColor - The color to blend with.
|
|
120
|
+
* @returns A new RGB color that is blended.
|
|
121
|
+
*/
|
|
122
|
+
blend(value, blendColor) {
|
|
123
|
+
return this.asRGB().blend(value, blendColor);
|
|
48
124
|
}
|
|
125
|
+
/**
|
|
126
|
+
* Sets the hue of the color.
|
|
127
|
+
* @param value - The new hue value.
|
|
128
|
+
* @returns A new HSV color with the hue set.
|
|
129
|
+
*/
|
|
49
130
|
setHue(value) {
|
|
50
|
-
return this.
|
|
131
|
+
return this.asHSV().setHue(value);
|
|
51
132
|
}
|
|
52
133
|
}
|
|
53
134
|
|
|
54
|
-
function clamp(
|
|
55
|
-
|
|
135
|
+
function clamp(value, min, max) {
|
|
136
|
+
if (value == null || isNaN(value))
|
|
137
|
+
return min;
|
|
138
|
+
if (value < min)
|
|
139
|
+
return min;
|
|
140
|
+
if (value > max)
|
|
141
|
+
return max;
|
|
142
|
+
return value;
|
|
56
143
|
}
|
|
57
|
-
function mod(
|
|
58
|
-
|
|
144
|
+
function mod(value, max) {
|
|
145
|
+
value = value % max;
|
|
146
|
+
if (value < 0)
|
|
147
|
+
value += max;
|
|
148
|
+
if (value == 0)
|
|
149
|
+
return 0;
|
|
150
|
+
return value;
|
|
59
151
|
}
|
|
60
152
|
function formatFloat(num, precision) {
|
|
61
153
|
return num.toFixed(precision).replace(/0+$/, '').replace(/\.$/, '');
|
|
62
154
|
}
|
|
63
155
|
|
|
156
|
+
/**
|
|
157
|
+
* Represents an RGB color with optional alpha transparency.
|
|
158
|
+
*
|
|
159
|
+
* @extends Color
|
|
160
|
+
*/
|
|
64
161
|
class RGB extends Color {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
162
|
+
/**
|
|
163
|
+
* Red component (0-255).
|
|
164
|
+
*/
|
|
165
|
+
r;
|
|
166
|
+
/**
|
|
167
|
+
* Green component (0-255).
|
|
168
|
+
*/
|
|
169
|
+
g;
|
|
170
|
+
/**
|
|
171
|
+
* Blue component (0-255).
|
|
172
|
+
*/
|
|
173
|
+
b;
|
|
174
|
+
/**
|
|
175
|
+
* Alpha component (0-1).
|
|
176
|
+
*/
|
|
177
|
+
a;
|
|
178
|
+
/**
|
|
179
|
+
* Creates an instance of RGB.
|
|
180
|
+
*
|
|
181
|
+
* @param r - Red component (0-255).
|
|
182
|
+
* @param g - Green component (0-255).
|
|
183
|
+
* @param b - Blue component (0-255).
|
|
184
|
+
* @param a - Alpha component (0-1), defaults to 1.
|
|
185
|
+
*/
|
|
69
186
|
constructor(r, g, b, a = 1) {
|
|
70
187
|
super();
|
|
71
188
|
this.r = clamp(r, 0, 255);
|
|
@@ -73,15 +190,35 @@ class RGB extends Color {
|
|
|
73
190
|
this.b = clamp(b, 0, 255);
|
|
74
191
|
this.a = clamp(a, 0, 1);
|
|
75
192
|
}
|
|
193
|
+
/**
|
|
194
|
+
* Creates a clone of the current RGB color.
|
|
195
|
+
*
|
|
196
|
+
* @returns A new RGB instance with the same color values.
|
|
197
|
+
*/
|
|
76
198
|
clone() {
|
|
77
199
|
return new RGB(this.r, this.g, this.b, this.a);
|
|
78
200
|
}
|
|
201
|
+
/**
|
|
202
|
+
* Returns the RGB color as an array.
|
|
203
|
+
*
|
|
204
|
+
* @returns An array containing the red, green, blue, and alpha components.
|
|
205
|
+
*/
|
|
79
206
|
asArray() {
|
|
80
207
|
return [this.r, this.g, this.b, this.a];
|
|
81
208
|
}
|
|
209
|
+
/**
|
|
210
|
+
* Rounds the RGB color components to the nearest integer.
|
|
211
|
+
*
|
|
212
|
+
* @returns A new RGB instance with rounded color values.
|
|
213
|
+
*/
|
|
82
214
|
round() {
|
|
83
215
|
return new RGB(Math.round(this.r), Math.round(this.g), Math.round(this.b), Math.round(this.a * 1000) / 1000);
|
|
84
216
|
}
|
|
217
|
+
/**
|
|
218
|
+
* Returns the RGB color as a string.
|
|
219
|
+
*
|
|
220
|
+
* @returns A string representation of the RGB color in either `rgb` or `rgba` format.
|
|
221
|
+
*/
|
|
85
222
|
asString() {
|
|
86
223
|
if (this.a === 1) {
|
|
87
224
|
return `rgb(${this.r.toFixed(0)},${this.g.toFixed(0)},${this.b.toFixed(0)})`;
|
|
@@ -90,6 +227,11 @@ class RGB extends Color {
|
|
|
90
227
|
return `rgba(${this.r.toFixed(0)},${this.g.toFixed(0)},${this.b.toFixed(0)},${formatFloat(this.a, 3)})`;
|
|
91
228
|
}
|
|
92
229
|
}
|
|
230
|
+
/**
|
|
231
|
+
* Returns the RGB color as a hexadecimal string.
|
|
232
|
+
*
|
|
233
|
+
* @returns A string representation of the RGB color in hexadecimal format.
|
|
234
|
+
*/
|
|
93
235
|
asHex() {
|
|
94
236
|
const r = Math.round(this.r).toString(16).padStart(2, '0');
|
|
95
237
|
const g = Math.round(this.g).toString(16).padStart(2, '0');
|
|
@@ -102,6 +244,11 @@ class RGB extends Color {
|
|
|
102
244
|
return `#${r}${g}${b}${a}`.toUpperCase();
|
|
103
245
|
}
|
|
104
246
|
}
|
|
247
|
+
/**
|
|
248
|
+
* Converts the RGB color to an HSL color.
|
|
249
|
+
*
|
|
250
|
+
* @returns An HSL instance representing the same color.
|
|
251
|
+
*/
|
|
105
252
|
asHSL() {
|
|
106
253
|
const r = this.r / 255;
|
|
107
254
|
const g = this.g / 255;
|
|
@@ -132,6 +279,11 @@ class RGB extends Color {
|
|
|
132
279
|
return new HSL(h, s * 100, l * 100, this.a);
|
|
133
280
|
}
|
|
134
281
|
;
|
|
282
|
+
/**
|
|
283
|
+
* Converts the RGB color to an HSV color.
|
|
284
|
+
*
|
|
285
|
+
* @returns An HSV instance representing the same color.
|
|
286
|
+
*/
|
|
135
287
|
asHSV() {
|
|
136
288
|
const r = this.r / 255;
|
|
137
289
|
const g = this.g / 255;
|
|
@@ -161,12 +313,29 @@ class RGB extends Color {
|
|
|
161
313
|
}
|
|
162
314
|
return new HSV(h * 360, s * 100, v * 100, this.a);
|
|
163
315
|
}
|
|
316
|
+
/**
|
|
317
|
+
* Returns the RGB color.
|
|
318
|
+
*
|
|
319
|
+
* @returns The current RGB instance.
|
|
320
|
+
*/
|
|
164
321
|
asRGB() {
|
|
165
322
|
return this.clone();
|
|
166
323
|
}
|
|
324
|
+
/**
|
|
325
|
+
* Returns the RGB color.
|
|
326
|
+
*
|
|
327
|
+
* @returns The current RGB instance.
|
|
328
|
+
*/
|
|
167
329
|
toRGB() {
|
|
168
330
|
return this;
|
|
169
331
|
}
|
|
332
|
+
/**
|
|
333
|
+
* Parses a string or Color instance into an RGB color.
|
|
334
|
+
*
|
|
335
|
+
* @param input - The input string or Color instance to parse.
|
|
336
|
+
* @returns A new RGB instance representing the parsed color.
|
|
337
|
+
* @throws Will throw an error if the input string is not a valid RGB color string.
|
|
338
|
+
*/
|
|
170
339
|
static parse(input) {
|
|
171
340
|
if (input instanceof Color)
|
|
172
341
|
return input.asRGB();
|
|
@@ -206,6 +375,12 @@ class RGB extends Color {
|
|
|
206
375
|
}
|
|
207
376
|
throw new Error(`Invalid RGB color string: "${input}"`);
|
|
208
377
|
}
|
|
378
|
+
/**
|
|
379
|
+
* Adjusts the gamma of the RGB color.
|
|
380
|
+
*
|
|
381
|
+
* @param value - The gamma value to apply.
|
|
382
|
+
* @returns A new RGB instance with the adjusted gamma.
|
|
383
|
+
*/
|
|
209
384
|
gamma(value) {
|
|
210
385
|
if (value < 1e-3)
|
|
211
386
|
value = 1e-3;
|
|
@@ -213,9 +388,20 @@ class RGB extends Color {
|
|
|
213
388
|
value = 1e3;
|
|
214
389
|
return new RGB(Math.pow(this.r / 255, value) * 255, Math.pow(this.g / 255, value) * 255, Math.pow(this.b / 255, value) * 255, this.a);
|
|
215
390
|
}
|
|
391
|
+
/**
|
|
392
|
+
* Inverts the RGB color.
|
|
393
|
+
*
|
|
394
|
+
* @returns A new RGB instance with the inverted color values.
|
|
395
|
+
*/
|
|
216
396
|
invert() {
|
|
217
397
|
return new RGB(255 - this.r, 255 - this.g, 255 - this.b, this.a);
|
|
218
398
|
}
|
|
399
|
+
/**
|
|
400
|
+
* Adjusts the contrast of the RGB color.
|
|
401
|
+
*
|
|
402
|
+
* @param value - The contrast value to apply.
|
|
403
|
+
* @returns A new RGB instance with the adjusted contrast.
|
|
404
|
+
*/
|
|
219
405
|
contrast(value) {
|
|
220
406
|
if (value < 0)
|
|
221
407
|
value = 0;
|
|
@@ -223,6 +409,12 @@ class RGB extends Color {
|
|
|
223
409
|
value = 1e6;
|
|
224
410
|
return new RGB(clamp((this.r - 127.5) * value + 127.5, 0, 255), clamp((this.g - 127.5) * value + 127.5, 0, 255), clamp((this.b - 127.5) * value + 127.5, 0, 255), this.a);
|
|
225
411
|
}
|
|
412
|
+
/**
|
|
413
|
+
* Adjusts the brightness of the RGB color.
|
|
414
|
+
*
|
|
415
|
+
* @param value - The brightness value to apply.
|
|
416
|
+
* @returns A new RGB instance with the adjusted brightness.
|
|
417
|
+
*/
|
|
226
418
|
brightness(value) {
|
|
227
419
|
if (value < -1)
|
|
228
420
|
value = -1;
|
|
@@ -232,30 +424,90 @@ class RGB extends Color {
|
|
|
232
424
|
const b = (value < 0) ? 0 : 255 * value;
|
|
233
425
|
return new RGB(this.r * a + b, this.g * a + b, this.b * a + b, this.a);
|
|
234
426
|
}
|
|
427
|
+
/**
|
|
428
|
+
* Tints the RGB color with another color.
|
|
429
|
+
*
|
|
430
|
+
* @param value - The tint value to apply.
|
|
431
|
+
* @param tintColor - The color to use for tinting.
|
|
432
|
+
* @returns A new RGB instance with the applied tint.
|
|
433
|
+
*/
|
|
235
434
|
tint(value, tintColor) {
|
|
236
435
|
if (value < 0)
|
|
237
436
|
value = 0;
|
|
238
437
|
if (value > 1)
|
|
239
438
|
value = 1;
|
|
240
|
-
const rgbNew = this.setHue(tintColor.
|
|
439
|
+
const rgbNew = this.setHue(tintColor.asHSV().h).asRGB();
|
|
241
440
|
return new RGB(this.r * (1 - value) + value * rgbNew.r, this.g * (1 - value) + value * rgbNew.g, this.b * (1 - value) + value * rgbNew.b, this.a);
|
|
242
441
|
}
|
|
442
|
+
/**
|
|
443
|
+
* Blends the RGB color with another color.
|
|
444
|
+
*
|
|
445
|
+
* @param value - The blend value to apply.
|
|
446
|
+
* @param blendColor - The color to blend with.
|
|
447
|
+
* @returns A new RGB instance with the blended color.
|
|
448
|
+
*/
|
|
449
|
+
blend(value, blendColor) {
|
|
450
|
+
value = clamp(value ?? 0, 0, 1);
|
|
451
|
+
const rgbNew = blendColor.asRGB();
|
|
452
|
+
return new RGB(this.r * (1 - value) + value * rgbNew.r, this.g * (1 - value) + value * rgbNew.g, this.b * (1 - value) + value * rgbNew.b, this.a);
|
|
453
|
+
}
|
|
454
|
+
/**
|
|
455
|
+
* Lightens the RGB color.
|
|
456
|
+
*
|
|
457
|
+
* @param ratio - The ratio to lighten the color by.
|
|
458
|
+
* @returns A new RGB instance with the lightened color.
|
|
459
|
+
*/
|
|
243
460
|
lighten(ratio) {
|
|
244
461
|
return new RGB(clamp(255 - (255 - this.r) * (1 - ratio), 0, 255), clamp(255 - (255 - this.g) * (1 - ratio), 0, 255), clamp(255 - (255 - this.b) * (1 - ratio), 0, 255), this.a);
|
|
245
462
|
}
|
|
463
|
+
/**
|
|
464
|
+
* Darkens the RGB color.
|
|
465
|
+
*
|
|
466
|
+
* @param ratio - The ratio to darken the color by.
|
|
467
|
+
* @returns A new RGB instance with the darkened color.
|
|
468
|
+
*/
|
|
246
469
|
darken(ratio) {
|
|
247
470
|
return new RGB(clamp(this.r * (1 - ratio), 0, 255), clamp(this.g * (1 - ratio), 0, 255), clamp(this.b * (1 - ratio), 0, 255), this.a);
|
|
248
471
|
}
|
|
472
|
+
/**
|
|
473
|
+
* Fades the RGB color by reducing its alpha value.
|
|
474
|
+
*
|
|
475
|
+
* @param value - The fade value to apply.
|
|
476
|
+
* @returns A new RGB instance with the faded color.
|
|
477
|
+
*/
|
|
249
478
|
fade(value) {
|
|
250
479
|
return new RGB(this.r, this.g, this.b, this.a * (1 - value));
|
|
251
480
|
}
|
|
252
481
|
}
|
|
253
482
|
|
|
483
|
+
/**
|
|
484
|
+
* Represents a color in the HSV (Hue, Saturation, Value) color space.
|
|
485
|
+
* Extends the base `Color` class.
|
|
486
|
+
*/
|
|
254
487
|
class HSV extends Color {
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
488
|
+
/**
|
|
489
|
+
* The hue component of the color, in the range [0, 360].
|
|
490
|
+
*/
|
|
491
|
+
h;
|
|
492
|
+
/**
|
|
493
|
+
* The saturation component of the color, in the range [0, 100].
|
|
494
|
+
*/
|
|
495
|
+
s;
|
|
496
|
+
/**
|
|
497
|
+
* The value (brightness) component of the color, in the range [0, 100].
|
|
498
|
+
*/
|
|
499
|
+
v;
|
|
500
|
+
/**
|
|
501
|
+
* The alpha (opacity) component of the color, in the range [0, 1].
|
|
502
|
+
*/
|
|
503
|
+
a;
|
|
504
|
+
/**
|
|
505
|
+
* Constructs a new HSV color.
|
|
506
|
+
* @param h - The hue component, in the range [0, 360].
|
|
507
|
+
* @param s - The saturation component, in the range [0, 100].
|
|
508
|
+
* @param v - The value (brightness) component, in the range [0, 100].
|
|
509
|
+
* @param a - The alpha (opacity) component, in the range [0, 1]. Defaults to 1.
|
|
510
|
+
*/
|
|
259
511
|
constructor(h, s, v, a = 1) {
|
|
260
512
|
super();
|
|
261
513
|
this.h = mod(h, 360);
|
|
@@ -263,18 +515,38 @@ class HSV extends Color {
|
|
|
263
515
|
this.v = clamp(v, 0, 100);
|
|
264
516
|
this.a = clamp(a, 0, 1);
|
|
265
517
|
}
|
|
518
|
+
/**
|
|
519
|
+
* Returns the HSV color as an array of numbers.
|
|
520
|
+
* @returns An array containing the hue, saturation, value, and alpha components.
|
|
521
|
+
*/
|
|
266
522
|
asArray() {
|
|
267
523
|
return [this.h, this.s, this.v, this.a];
|
|
268
524
|
}
|
|
525
|
+
/**
|
|
526
|
+
* Returns a new HSV color with the components rounded to the nearest integer.
|
|
527
|
+
* @returns A new HSV color with rounded components.
|
|
528
|
+
*/
|
|
269
529
|
round() {
|
|
270
530
|
return new HSV(Math.round(this.h), Math.round(this.s), Math.round(this.v), Math.round(this.a * 1000) / 1000);
|
|
271
531
|
}
|
|
532
|
+
/**
|
|
533
|
+
* Returns the color as a string representation.
|
|
534
|
+
* @returns A string representation of the color.
|
|
535
|
+
*/
|
|
272
536
|
asString() {
|
|
273
537
|
return this.asHSL().asString();
|
|
274
538
|
}
|
|
539
|
+
/**
|
|
540
|
+
* Creates a new HSV color that is a copy of the current color.
|
|
541
|
+
* @returns A new HSV color that is a clone of the current color.
|
|
542
|
+
*/
|
|
275
543
|
clone() {
|
|
276
544
|
return new HSV(this.h, this.s, this.v, this.a);
|
|
277
545
|
}
|
|
546
|
+
/**
|
|
547
|
+
* Converts the HSV color to an HSL color.
|
|
548
|
+
* @returns An HSL representation of the color.
|
|
549
|
+
*/
|
|
278
550
|
asHSL() {
|
|
279
551
|
const s = this.s / 100;
|
|
280
552
|
const v = this.v / 100;
|
|
@@ -282,12 +554,24 @@ class HSV extends Color {
|
|
|
282
554
|
const q = k < 1 ? k : 2 - k;
|
|
283
555
|
return new HSL(this.h, q == 0 ? 0 : 100 * s * v / q, 100 * k / 2, this.a);
|
|
284
556
|
}
|
|
557
|
+
/**
|
|
558
|
+
* Returns the current HSV color.
|
|
559
|
+
* @returns The current HSV color.
|
|
560
|
+
*/
|
|
285
561
|
asHSV() {
|
|
286
562
|
return this.clone();
|
|
287
563
|
}
|
|
564
|
+
/**
|
|
565
|
+
* Returns the current HSV color.
|
|
566
|
+
* @returns The current HSV color.
|
|
567
|
+
*/
|
|
288
568
|
toHSV() {
|
|
289
569
|
return this;
|
|
290
570
|
}
|
|
571
|
+
/**
|
|
572
|
+
* Converts the HSV color to an RGB color.
|
|
573
|
+
* @returns An RGB representation of the color.
|
|
574
|
+
*/
|
|
291
575
|
asRGB() {
|
|
292
576
|
const h = this.h / 360; // Normalize h to range [0, 1]
|
|
293
577
|
const s = this.s / 100; // Normalize s to range [0, 1]
|
|
@@ -339,19 +623,52 @@ class HSV extends Color {
|
|
|
339
623
|
// Convert to RGB in the 0-255 range and return
|
|
340
624
|
return new RGB(r * 255, g * 255, b * 255, this.a);
|
|
341
625
|
}
|
|
626
|
+
/**
|
|
627
|
+
* Fades the color by a given value.
|
|
628
|
+
* @param value - The amount to fade the color by, in the range [0, 1].
|
|
629
|
+
* @returns A new HSV color with the alpha component faded by the given value.
|
|
630
|
+
*/
|
|
342
631
|
fade(value) {
|
|
343
632
|
return new HSV(this.h, this.s, this.v, this.a * (1 - value));
|
|
344
633
|
}
|
|
634
|
+
/**
|
|
635
|
+
* Sets the hue component of the color.
|
|
636
|
+
* @param value - The new hue value, in the range [0, 360].
|
|
637
|
+
* @returns A new HSV color with the updated hue component.
|
|
638
|
+
*/
|
|
345
639
|
setHue(value) {
|
|
346
640
|
return new HSV(value, this.s, this.v, this.a);
|
|
347
641
|
}
|
|
348
642
|
}
|
|
349
643
|
|
|
644
|
+
/**
|
|
645
|
+
* Represents a color in the HSL (Hue, Saturation, Lightness) color space.
|
|
646
|
+
* Extends the base `Color` class.
|
|
647
|
+
*/
|
|
350
648
|
class HSL extends Color {
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
649
|
+
/**
|
|
650
|
+
* The hue component of the color, in the range [0, 360].
|
|
651
|
+
*/
|
|
652
|
+
h;
|
|
653
|
+
/**
|
|
654
|
+
* The saturation component of the color, in the range [0, 100].
|
|
655
|
+
*/
|
|
656
|
+
s;
|
|
657
|
+
/**
|
|
658
|
+
* The lightness component of the color, in the range [0, 100].
|
|
659
|
+
*/
|
|
660
|
+
l;
|
|
661
|
+
/**
|
|
662
|
+
* The alpha (opacity) component of the color, in the range [0, 1].
|
|
663
|
+
*/
|
|
664
|
+
a;
|
|
665
|
+
/**
|
|
666
|
+
* Creates a new HSL color.
|
|
667
|
+
* @param h - The hue component, in the range [0, 360].
|
|
668
|
+
* @param s - The saturation component, in the range [0, 100].
|
|
669
|
+
* @param l - The lightness component, in the range [0, 100].
|
|
670
|
+
* @param a - The alpha (opacity) component, in the range [0, 1]. Defaults to 1.
|
|
671
|
+
*/
|
|
355
672
|
constructor(h, s, l, a = 1) {
|
|
356
673
|
super();
|
|
357
674
|
this.h = mod(h, 360);
|
|
@@ -359,15 +676,31 @@ class HSL extends Color {
|
|
|
359
676
|
this.l = clamp(l, 0, 100);
|
|
360
677
|
this.a = clamp(a, 0, 1);
|
|
361
678
|
}
|
|
679
|
+
/**
|
|
680
|
+
* Returns the HSL color as an array of numbers.
|
|
681
|
+
* @returns An array containing the hue, saturation, lightness, and alpha components.
|
|
682
|
+
*/
|
|
362
683
|
asArray() {
|
|
363
684
|
return [this.h, this.s, this.l, this.a];
|
|
364
685
|
}
|
|
686
|
+
/**
|
|
687
|
+
* Returns a new HSL color with rounded components.
|
|
688
|
+
* @returns A new HSL color with rounded hue, saturation, lightness, and alpha components.
|
|
689
|
+
*/
|
|
365
690
|
round() {
|
|
366
691
|
return new HSL(Math.round(this.h), Math.round(this.s), Math.round(this.l), Math.round(this.a * 1000) / 1000);
|
|
367
692
|
}
|
|
693
|
+
/**
|
|
694
|
+
* Creates a copy of the current HSL color.
|
|
695
|
+
* @returns A new HSL color with the same components as the current color.
|
|
696
|
+
*/
|
|
368
697
|
clone() {
|
|
369
698
|
return new HSL(this.h, this.s, this.l, this.a);
|
|
370
699
|
}
|
|
700
|
+
/**
|
|
701
|
+
* Returns the HSL color as a CSS-compatible string.
|
|
702
|
+
* @returns A string representing the HSL color in CSS format.
|
|
703
|
+
*/
|
|
371
704
|
asString() {
|
|
372
705
|
if (this.a === 1) {
|
|
373
706
|
return `hsl(${this.h.toFixed(0)},${this.s.toFixed(0)}%,${this.l.toFixed(0)}%)`;
|
|
@@ -376,18 +709,34 @@ class HSL extends Color {
|
|
|
376
709
|
return `hsla(${this.h.toFixed(0)},${this.s.toFixed(0)}%,${this.l.toFixed(0)}%,${formatFloat(this.a, 3)})`;
|
|
377
710
|
}
|
|
378
711
|
}
|
|
712
|
+
/**
|
|
713
|
+
* Returns the current HSL color.
|
|
714
|
+
* @returns The current HSL color.
|
|
715
|
+
*/
|
|
379
716
|
asHSL() {
|
|
380
717
|
return this.clone();
|
|
381
718
|
}
|
|
719
|
+
/**
|
|
720
|
+
* Returns the current HSL color.
|
|
721
|
+
* @returns The current HSL color.
|
|
722
|
+
*/
|
|
382
723
|
toHSL() {
|
|
383
724
|
return this;
|
|
384
725
|
}
|
|
726
|
+
/**
|
|
727
|
+
* Converts the HSL color to an HSV color.
|
|
728
|
+
* @returns A new HSV color representing the same color.
|
|
729
|
+
*/
|
|
385
730
|
asHSV() {
|
|
386
731
|
const s = this.s / 100, l = this.l / 100;
|
|
387
732
|
const v = l + s * Math.min(l, 1 - l);
|
|
388
733
|
const sv = v === 0 ? 0 : 2 * (1 - l / v);
|
|
389
734
|
return new HSV(this.h, sv * 100, v * 100, this.a);
|
|
390
735
|
}
|
|
736
|
+
/**
|
|
737
|
+
* Converts the HSL color to an RGB color.
|
|
738
|
+
* @returns A new RGB color representing the same color.
|
|
739
|
+
*/
|
|
391
740
|
asRGB() {
|
|
392
741
|
const h = this.h / 360;
|
|
393
742
|
const s = this.s / 100;
|
|
@@ -413,6 +762,12 @@ class HSL extends Color {
|
|
|
413
762
|
// Convert to RGB in the 0-255 range and return
|
|
414
763
|
return new RGB(255 * hueToRgb(h + 1 / 3), 255 * hueToRgb(h), 255 * hueToRgb(h - 1 / 3), this.a);
|
|
415
764
|
}
|
|
765
|
+
/**
|
|
766
|
+
* Parses a string or Color object into an HSL color.
|
|
767
|
+
* @param input - The input string or Color object to parse.
|
|
768
|
+
* @returns A new HSL color parsed from the input.
|
|
769
|
+
* @throws Will throw an error if the input string is not a valid HSL color string.
|
|
770
|
+
*/
|
|
416
771
|
static parse(input) {
|
|
417
772
|
if (input instanceof Color)
|
|
418
773
|
return input.asHSL();
|
|
@@ -427,150 +782,39 @@ class HSL extends Color {
|
|
|
427
782
|
}
|
|
428
783
|
throw new Error(`Invalid HSL color string: "${input}"`);
|
|
429
784
|
}
|
|
785
|
+
/**
|
|
786
|
+
* Inverts the lightness component of the HSL color.
|
|
787
|
+
* @returns A new HSL color with the lightness component inverted.
|
|
788
|
+
*/
|
|
430
789
|
invertLuminosity() {
|
|
431
790
|
return new HSL(this.h, this.s, 100 - this.l, this.a);
|
|
432
791
|
}
|
|
792
|
+
/**
|
|
793
|
+
* Rotates the hue component of the HSL color by a given offset.
|
|
794
|
+
* @param offset - The amount to rotate the hue by, in degrees.
|
|
795
|
+
* @returns A new HSL color with the hue rotated by the given offset.
|
|
796
|
+
*/
|
|
433
797
|
rotateHue(offset) {
|
|
434
798
|
return new HSL(mod(this.h + offset, 360), this.s, this.l, this.a);
|
|
435
799
|
}
|
|
800
|
+
/**
|
|
801
|
+
* Increases the saturation of the HSL color by a given ratio.
|
|
802
|
+
* @param ratio - The ratio by which to increase the saturation.
|
|
803
|
+
* @returns A new HSL color with increased saturation.
|
|
804
|
+
*/
|
|
436
805
|
saturate(ratio) {
|
|
437
806
|
return new HSL(this.h, clamp(this.s * (1 + ratio), 0, 100), this.l, this.a);
|
|
438
807
|
}
|
|
808
|
+
/**
|
|
809
|
+
* Decreases the alpha (opacity) of the HSL color by a given value.
|
|
810
|
+
* @param value - The value by which to decrease the alpha.
|
|
811
|
+
* @returns A new HSL color with decreased alpha.
|
|
812
|
+
*/
|
|
439
813
|
fade(value) {
|
|
440
814
|
return new HSL(this.h, this.s, this.l, this.a * (1 - value));
|
|
441
815
|
}
|
|
442
816
|
}
|
|
443
817
|
|
|
444
|
-
let colorDictionary = new Map();
|
|
445
|
-
function randomColor(options) {
|
|
446
|
-
if (colorDictionary.size === 0)
|
|
447
|
-
colorDictionary = initColorDictionary();
|
|
448
|
-
options ??= {};
|
|
449
|
-
let seed = inputToSeed(options.seed);
|
|
450
|
-
const H = pickHue(options);
|
|
451
|
-
const S = pickSaturation(H, options);
|
|
452
|
-
const V = pickBrightness(H, S, options);
|
|
453
|
-
return new HSV(H, S, V, options.opacity ?? 1);
|
|
454
|
-
function pickHue(options) {
|
|
455
|
-
return mod(randomWithin(getHueRange(options.hue)), 360);
|
|
456
|
-
function getHueRange(hue) {
|
|
457
|
-
if (typeof hue === 'number') {
|
|
458
|
-
hue = mod(hue, 360);
|
|
459
|
-
return [hue, hue];
|
|
460
|
-
}
|
|
461
|
-
if (typeof hue === 'string') {
|
|
462
|
-
const color = colorDictionary.get(hue);
|
|
463
|
-
if (color?.hueRange)
|
|
464
|
-
return color.hueRange;
|
|
465
|
-
}
|
|
466
|
-
return [0, 360];
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
function pickSaturation(hue, options) {
|
|
470
|
-
if (options.hue === 'monochrome')
|
|
471
|
-
return 0;
|
|
472
|
-
if (options.luminosity === 'random')
|
|
473
|
-
return randomWithin([0, 100]);
|
|
474
|
-
let [sMin, sMax] = getColorInfo(hue).saturationRange;
|
|
475
|
-
if (options.saturation === 'strong')
|
|
476
|
-
return sMax;
|
|
477
|
-
switch (options.luminosity) {
|
|
478
|
-
case 'bright':
|
|
479
|
-
sMin = 55;
|
|
480
|
-
break;
|
|
481
|
-
case 'dark':
|
|
482
|
-
sMin = sMax - 10;
|
|
483
|
-
break;
|
|
484
|
-
case 'light':
|
|
485
|
-
sMax = 55;
|
|
486
|
-
break;
|
|
487
|
-
}
|
|
488
|
-
return randomWithin([sMin, sMax]);
|
|
489
|
-
}
|
|
490
|
-
function pickBrightness(h, s, options) {
|
|
491
|
-
let bMin = getMinimumBrightness(h, s), bMax = 100;
|
|
492
|
-
if (typeof options.luminosity === 'number') {
|
|
493
|
-
bMin = options.luminosity;
|
|
494
|
-
bMax = options.luminosity;
|
|
495
|
-
}
|
|
496
|
-
else {
|
|
497
|
-
switch (options.luminosity) {
|
|
498
|
-
case 'dark':
|
|
499
|
-
bMax = Math.min(100, bMin + 20);
|
|
500
|
-
break;
|
|
501
|
-
case 'light':
|
|
502
|
-
bMin = (bMax + bMin) / 2;
|
|
503
|
-
break;
|
|
504
|
-
case 'random':
|
|
505
|
-
bMin = 0;
|
|
506
|
-
bMax = 100;
|
|
507
|
-
break;
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
return randomWithin([bMin, bMax]);
|
|
511
|
-
function getMinimumBrightness(h, s) {
|
|
512
|
-
const { lowerBounds } = getColorInfo(h);
|
|
513
|
-
for (let i = 0; i < lowerBounds.length - 1; i++) {
|
|
514
|
-
const [s1, v1] = lowerBounds[i];
|
|
515
|
-
const [s2, v2] = lowerBounds[i + 1];
|
|
516
|
-
if (s >= s1 && s <= s2) {
|
|
517
|
-
const m = (v2 - v1) / (s2 - s1), b = v1 - m * s1;
|
|
518
|
-
return m * s + b;
|
|
519
|
-
}
|
|
520
|
-
}
|
|
521
|
-
return 0;
|
|
522
|
-
}
|
|
523
|
-
}
|
|
524
|
-
function randomWithin(range) {
|
|
525
|
-
//Seeded random algorithm from http://indiegamr.com/generate-repeatable-random-numbers-in-js/
|
|
526
|
-
seed = (seed * 9301 + 49297) % 233280;
|
|
527
|
-
return Math.floor(range[0] + seed / 233280.0 * (range[1] - range[0]));
|
|
528
|
-
}
|
|
529
|
-
}
|
|
530
|
-
function inputToSeed(input) {
|
|
531
|
-
if (input == null)
|
|
532
|
-
return 0;
|
|
533
|
-
if (typeof input === 'number')
|
|
534
|
-
return input;
|
|
535
|
-
let i = 0;
|
|
536
|
-
for (let p = 0; p < input.length; p++)
|
|
537
|
-
i = (i * 0x101 + input.charCodeAt(p)) % 0x100000000;
|
|
538
|
-
return i;
|
|
539
|
-
}
|
|
540
|
-
function initColorDictionary() {
|
|
541
|
-
const dict = new Map();
|
|
542
|
-
const defineColor = (name, hueRange, lowerBounds) => {
|
|
543
|
-
const [greyest] = lowerBounds;
|
|
544
|
-
const colorful = lowerBounds[lowerBounds.length - 1];
|
|
545
|
-
dict.set(name, {
|
|
546
|
-
hueRange,
|
|
547
|
-
lowerBounds,
|
|
548
|
-
saturationRange: [greyest[0], colorful[0]],
|
|
549
|
-
brightnessRange: [colorful[1], greyest[1]],
|
|
550
|
-
});
|
|
551
|
-
};
|
|
552
|
-
defineColor('monochrome', null, [[0, 0], [100, 0]]);
|
|
553
|
-
defineColor('red', [-26, 18], [[20, 100], [30, 92], [40, 89], [50, 85], [60, 78], [70, 70], [80, 60], [90, 55], [100, 50]]);
|
|
554
|
-
defineColor('orange', [18, 46], [[20, 100], [30, 93], [40, 88], [50, 86], [60, 85], [70, 70], [100, 70]]);
|
|
555
|
-
defineColor('yellow', [46, 62], [[25, 100], [40, 94], [50, 89], [60, 86], [70, 84], [80, 82], [90, 80], [100, 75]]);
|
|
556
|
-
defineColor('green', [62, 178], [[30, 100], [40, 90], [50, 85], [60, 81], [70, 74], [80, 64], [90, 50], [100, 40]]);
|
|
557
|
-
defineColor('blue', [178, 257], [[20, 100], [30, 86], [40, 80], [50, 74], [60, 60], [70, 52], [80, 44], [90, 39], [100, 35]]);
|
|
558
|
-
defineColor('purple', [257, 282], [[20, 100], [30, 87], [40, 79], [50, 70], [60, 65], [70, 59], [80, 52], [90, 45], [100, 42]]);
|
|
559
|
-
defineColor('pink', [282, 334], [[20, 100], [30, 90], [40, 86], [60, 84], [80, 80], [90, 75], [100, 73]]);
|
|
560
|
-
return dict;
|
|
561
|
-
}
|
|
562
|
-
function getColorInfo(hue) {
|
|
563
|
-
hue = mod(hue, 360);
|
|
564
|
-
if (hue >= 334)
|
|
565
|
-
hue -= 360;
|
|
566
|
-
for (const color of colorDictionary.values()) {
|
|
567
|
-
if (color.hueRange && hue >= color.hueRange[0] && hue <= color.hueRange[1]) {
|
|
568
|
-
return color;
|
|
569
|
-
}
|
|
570
|
-
}
|
|
571
|
-
throw Error('Color hue value not found');
|
|
572
|
-
}
|
|
573
|
-
|
|
574
818
|
Color.parse = function (input) {
|
|
575
819
|
if (input instanceof Color)
|
|
576
820
|
return input;
|
|
@@ -592,7 +836,6 @@ Color.parse = function (input) {
|
|
|
592
836
|
Color.HSL = HSL;
|
|
593
837
|
Color.HSV = HSV;
|
|
594
838
|
Color.RGB = RGB;
|
|
595
|
-
Color.random = randomColor;
|
|
596
839
|
|
|
597
840
|
const maxzoom = 14;
|
|
598
841
|
function getShortbreadTemplate() {
|
|
@@ -796,7 +1039,6 @@ function getShortbreadLayers(option) {
|
|
|
796
1039
|
});
|
|
797
1040
|
});
|
|
798
1041
|
// no links
|
|
799
|
-
const noDrivewayExpression = ['!=', 'service', 'driveway'];
|
|
800
1042
|
['track', 'pedestrian', 'service', 'living_street', 'residential', 'unclassified'].forEach(t => {
|
|
801
1043
|
results.push({
|
|
802
1044
|
id: prefix + 'street-' + t.replace(/_/g, '') + suffix,
|
|
@@ -805,7 +1047,6 @@ function getShortbreadLayers(option) {
|
|
|
805
1047
|
filter: ['all',
|
|
806
1048
|
['==', 'kind', t],
|
|
807
1049
|
...filter,
|
|
808
|
-
...(t === 'service') ? [noDrivewayExpression] : [], // ignore driveways
|
|
809
1050
|
],
|
|
810
1051
|
});
|
|
811
1052
|
});
|
|
@@ -820,7 +1061,6 @@ function getShortbreadLayers(option) {
|
|
|
820
1061
|
['==', 'kind', t],
|
|
821
1062
|
['==', 'bicycle', 'designated'],
|
|
822
1063
|
...filter,
|
|
823
|
-
...(t === 'service') ? [noDrivewayExpression] : [], // ignore driveways
|
|
824
1064
|
],
|
|
825
1065
|
});
|
|
826
1066
|
});
|
|
@@ -853,8 +1093,9 @@ function getShortbreadLayers(option) {
|
|
|
853
1093
|
});
|
|
854
1094
|
// separate outline for trains
|
|
855
1095
|
[':outline', ''].forEach(suffix => {
|
|
856
|
-
//
|
|
857
|
-
['rail', 'light_rail', 'subway', 'narrow_gauge', 'tram'
|
|
1096
|
+
// with service distinction
|
|
1097
|
+
['rail', 'light_rail', 'subway', 'narrow_gauge', 'tram'].reverse().forEach((t) => {
|
|
1098
|
+
// main rail
|
|
858
1099
|
results.push({
|
|
859
1100
|
id: prefix + 'transport-' + t.replace(/_/g, '') + suffix,
|
|
860
1101
|
type: 'line',
|
|
@@ -865,6 +1106,29 @@ function getShortbreadLayers(option) {
|
|
|
865
1106
|
...filter,
|
|
866
1107
|
],
|
|
867
1108
|
});
|
|
1109
|
+
// service rail (crossover, siding, spur, yard)
|
|
1110
|
+
results.push({
|
|
1111
|
+
id: prefix + 'transport-' + t.replace(/_/g, '') + '-service' + suffix,
|
|
1112
|
+
type: 'line',
|
|
1113
|
+
'source-layer': 'streets',
|
|
1114
|
+
filter: ['all',
|
|
1115
|
+
['in', 'kind', t],
|
|
1116
|
+
['has', 'service'],
|
|
1117
|
+
...filter,
|
|
1118
|
+
],
|
|
1119
|
+
});
|
|
1120
|
+
});
|
|
1121
|
+
// other transport
|
|
1122
|
+
['funicular', 'monorail', 'bus_guideway', 'busway'].reverse().forEach((t) => {
|
|
1123
|
+
results.push({
|
|
1124
|
+
id: prefix + 'transport-' + t.replace(/_/g, '') + suffix,
|
|
1125
|
+
type: 'line',
|
|
1126
|
+
'source-layer': 'streets',
|
|
1127
|
+
filter: ['all',
|
|
1128
|
+
['in', 'kind', t],
|
|
1129
|
+
...filter,
|
|
1130
|
+
],
|
|
1131
|
+
});
|
|
868
1132
|
});
|
|
869
1133
|
if (c === 'street') {
|
|
870
1134
|
// aerialway, no bridges, above street evel
|
|
@@ -1377,7 +1641,7 @@ function expand (str, isTop) {
|
|
|
1377
1641
|
const isOptions = m.body.indexOf(',') >= 0;
|
|
1378
1642
|
if (!isSequence && !isOptions) {
|
|
1379
1643
|
// {a},b}
|
|
1380
|
-
if (m.post.match(
|
|
1644
|
+
if (m.post.match(/,(?!,).*\}/)) {
|
|
1381
1645
|
str = m.pre + '{' + m.body + escClose + m.post;
|
|
1382
1646
|
return expand(str)
|
|
1383
1647
|
}
|
|
@@ -1828,6 +2092,13 @@ function decorate(layers, rules, recolor) {
|
|
|
1828
2092
|
}
|
|
1829
2093
|
}
|
|
1830
2094
|
|
|
2095
|
+
/**
|
|
2096
|
+
* Module for applying various color transformations such as hue rotation, saturation, contrast, brightness,
|
|
2097
|
+
* tinting, and blending. These transformations are defined through the `RecolorOptions` interface.
|
|
2098
|
+
*/
|
|
2099
|
+
/**
|
|
2100
|
+
* Returns the default recolor settings.
|
|
2101
|
+
*/
|
|
1831
2102
|
function getDefaultRecolorFlags() {
|
|
1832
2103
|
return {
|
|
1833
2104
|
invertBrightness: false,
|
|
@@ -1838,70 +2109,90 @@ function getDefaultRecolorFlags() {
|
|
|
1838
2109
|
brightness: 0,
|
|
1839
2110
|
tint: 0,
|
|
1840
2111
|
tintColor: '#FF0000',
|
|
2112
|
+
blend: 0,
|
|
2113
|
+
blendColor: '#000000',
|
|
1841
2114
|
};
|
|
1842
2115
|
}
|
|
2116
|
+
/**
|
|
2117
|
+
* Checks if the given options object contains any active recolor transformations.
|
|
2118
|
+
* @param opt The recolor options to validate.
|
|
2119
|
+
*/
|
|
1843
2120
|
function isValidRecolorOptions(opt) {
|
|
1844
2121
|
if (!opt)
|
|
1845
2122
|
return false;
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
if ((opt.brightness != null) && (opt.brightness !== 0))
|
|
1857
|
-
return true;
|
|
1858
|
-
if ((opt.tint != null) && (opt.tint !== 0))
|
|
1859
|
-
return true;
|
|
1860
|
-
if ((opt.tintColor != null) && (opt.tintColor !== '#FF0000'))
|
|
1861
|
-
return true;
|
|
1862
|
-
return false;
|
|
2123
|
+
return (opt.invertBrightness ||
|
|
2124
|
+
(opt.rotate != null && opt.rotate !== 0) ||
|
|
2125
|
+
(opt.saturate != null && opt.saturate !== 0) ||
|
|
2126
|
+
(opt.gamma != null && opt.gamma !== 1) ||
|
|
2127
|
+
(opt.contrast != null && opt.contrast !== 1) ||
|
|
2128
|
+
(opt.brightness != null && opt.brightness !== 0) ||
|
|
2129
|
+
(opt.tint != null && opt.tint !== 0) ||
|
|
2130
|
+
(opt.tintColor != null && opt.tintColor !== '#FF0000') ||
|
|
2131
|
+
(opt.blend != null && opt.blend !== 0) ||
|
|
2132
|
+
(opt.blendColor != null && opt.blendColor !== '#000000'));
|
|
1863
2133
|
}
|
|
2134
|
+
/**
|
|
2135
|
+
* Caches recolored colors to optimize performance.
|
|
2136
|
+
*/
|
|
1864
2137
|
class CachedRecolor {
|
|
1865
2138
|
skip;
|
|
1866
2139
|
opt;
|
|
1867
2140
|
cache;
|
|
2141
|
+
/**
|
|
2142
|
+
* Creates a cached recolor instance.
|
|
2143
|
+
* @param opt Optional recolor options.
|
|
2144
|
+
*/
|
|
1868
2145
|
constructor(opt) {
|
|
1869
2146
|
this.skip = !isValidRecolorOptions(opt);
|
|
1870
2147
|
this.cache = new Map();
|
|
1871
2148
|
this.opt = opt;
|
|
1872
2149
|
}
|
|
2150
|
+
/**
|
|
2151
|
+
* Applies cached recoloring to a given color.
|
|
2152
|
+
* @param color The color to recolor.
|
|
2153
|
+
* @returns The recolored color, either from cache or newly computed.
|
|
2154
|
+
*/
|
|
1873
2155
|
do(color) {
|
|
1874
2156
|
if (this.skip)
|
|
1875
2157
|
return color;
|
|
1876
2158
|
const key = color.asHex();
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
return color;
|
|
2159
|
+
if (this.cache.has(key))
|
|
2160
|
+
return this.cache.get(key);
|
|
2161
|
+
const recolored = recolor(color, this.opt);
|
|
2162
|
+
this.cache.set(key, recolored);
|
|
2163
|
+
return recolored;
|
|
1883
2164
|
}
|
|
1884
2165
|
}
|
|
2166
|
+
/**
|
|
2167
|
+
* Applies the specified recoloring transformations to a single color.
|
|
2168
|
+
* @param color The original color.
|
|
2169
|
+
* @param opt Optional recolor options.
|
|
2170
|
+
* @returns A new `Color` instance with applied transformations.
|
|
2171
|
+
*/
|
|
1885
2172
|
function recolor(color, opt) {
|
|
1886
2173
|
if (!isValidRecolorOptions(opt))
|
|
1887
2174
|
return color;
|
|
1888
|
-
if (opt.invertBrightness
|
|
2175
|
+
if (opt.invertBrightness)
|
|
1889
2176
|
color = color.invertLuminosity();
|
|
1890
|
-
if (
|
|
2177
|
+
if (opt.rotate)
|
|
1891
2178
|
color = color.rotateHue(opt.rotate);
|
|
1892
|
-
if (
|
|
2179
|
+
if (opt.saturate)
|
|
1893
2180
|
color = color.saturate(opt.saturate);
|
|
1894
|
-
if (
|
|
2181
|
+
if (opt.gamma != null && opt.gamma != 1)
|
|
1895
2182
|
color = color.gamma(opt.gamma);
|
|
1896
|
-
if (
|
|
2183
|
+
if (opt.contrast != null && opt.contrast != 1)
|
|
1897
2184
|
color = color.contrast(opt.contrast);
|
|
1898
|
-
if (
|
|
2185
|
+
if (opt.brightness)
|
|
1899
2186
|
color = color.brightness(opt.brightness);
|
|
1900
|
-
if (
|
|
2187
|
+
if (opt.tint && opt.tintColor != null)
|
|
1901
2188
|
color = color.tint(opt.tint, Color.parse(opt.tintColor));
|
|
2189
|
+
if (opt.blend && opt.blendColor != null)
|
|
2190
|
+
color = color.blend(opt.blend, Color.parse(opt.blendColor));
|
|
1902
2191
|
return color;
|
|
1903
2192
|
}
|
|
1904
2193
|
|
|
2194
|
+
const styleBuilderColorKeys = ['agriculture', 'boundary', 'building', 'buildingbg', 'burial', 'commercial', 'construction', 'cycle', 'danger', 'disputed', 'education', 'foot', 'glacier', 'grass', 'hospital', 'industrial', 'label', 'labelHalo', 'land', 'leisure', 'motorway', 'motorwaybg', 'park', 'parking', 'poi', 'prison', 'rail', 'residential', 'rock', 'sand', 'shield', 'street', 'streetbg', 'subway', 'symbol', 'trunk', 'trunkbg', 'waste', 'water', 'wetland', 'wood'];
|
|
2195
|
+
|
|
1905
2196
|
// StyleBuilder class definition
|
|
1906
2197
|
class StyleBuilder {
|
|
1907
2198
|
#sourceName = 'versatiles-shortbread';
|
|
@@ -2005,8 +2296,7 @@ class StyleBuilder {
|
|
|
2005
2296
|
}
|
|
2006
2297
|
transformDefaultColors(callback) {
|
|
2007
2298
|
const colors = this.getColors(this.defaultColors);
|
|
2008
|
-
|
|
2009
|
-
for (key in colors) {
|
|
2299
|
+
for (const key of styleBuilderColorKeys) {
|
|
2010
2300
|
this.defaultColors[key] = callback(colors[key]);
|
|
2011
2301
|
}
|
|
2012
2302
|
}
|
|
@@ -2463,15 +2753,26 @@ class Colorful extends StyleBuilder {
|
|
|
2463
2753
|
size: { 12: 1, 14: 2, 16: 5, 18: 24, 19: 60, 20: 120 },
|
|
2464
2754
|
opacity: { 12: 0, 13: 1 },
|
|
2465
2755
|
},
|
|
2466
|
-
//
|
|
2467
|
-
'{bridge-,tunnel-,}street-
|
|
2756
|
+
// tracks
|
|
2757
|
+
'{bridge-,tunnel-,}street-track:outline': {
|
|
2468
2758
|
size: { 14: 2, 16: 4, 18: 18, 19: 48, 20: 96 },
|
|
2469
2759
|
opacity: { 14: 0, 15: 1 },
|
|
2470
2760
|
},
|
|
2471
|
-
'{bridge-,tunnel-,}street-
|
|
2761
|
+
'{bridge-,tunnel-,}street-track': {
|
|
2472
2762
|
size: { 14: 1, 16: 3, 18: 16, 19: 44, 20: 88 },
|
|
2473
2763
|
opacity: { 14: 0, 15: 1 },
|
|
2474
2764
|
},
|
|
2765
|
+
// service
|
|
2766
|
+
'{bridge-,tunnel-,}street-service:outline': {
|
|
2767
|
+
size: { 14: 1, 16: 3, 18: 12, 19: 32, 20: 48 },
|
|
2768
|
+
opacity: { 15: 0, 16: 1 },
|
|
2769
|
+
color: colors.streetbg.lighten(0.3),
|
|
2770
|
+
},
|
|
2771
|
+
'{bridge-,tunnel-,}street-service': {
|
|
2772
|
+
size: { 14: 1, 16: 2, 18: 10, 19: 28, 20: 40 },
|
|
2773
|
+
opacity: { 15: 0, 16: 1 },
|
|
2774
|
+
color: colors.street.darken(0.03),
|
|
2775
|
+
},
|
|
2475
2776
|
// ways
|
|
2476
2777
|
'{bridge-,tunnel-,}way-*:outline': {
|
|
2477
2778
|
size: { 15: 0, 16: 5, 18: 7, 19: 12, 20: 22 },
|
|
@@ -2511,7 +2812,8 @@ class Colorful extends StyleBuilder {
|
|
|
2511
2812
|
},
|
|
2512
2813
|
// cycle streets overlay
|
|
2513
2814
|
'{bridge-,tunnel-,}street-{tertiary,tertiary-link,unclassified,residential,livingstreet,pedestrian}-bicycle': {
|
|
2514
|
-
|
|
2815
|
+
lineJoin: 'round',
|
|
2816
|
+
lineCap: 'round',
|
|
2515
2817
|
color: colors.cycle,
|
|
2516
2818
|
},
|
|
2517
2819
|
// pedestrian
|
|
@@ -2527,11 +2829,25 @@ class Colorful extends StyleBuilder {
|
|
|
2527
2829
|
// rail, lightrail
|
|
2528
2830
|
'{tunnel-,bridge-,}transport-{rail,lightrail}:outline': {
|
|
2529
2831
|
color: colors.rail,
|
|
2530
|
-
|
|
2832
|
+
minzoom: 8,
|
|
2833
|
+
size: { 8: 1, 13: 1, 15: 1, 20: 14 },
|
|
2531
2834
|
},
|
|
2532
2835
|
'{tunnel-,bridge-,}transport-{rail,lightrail}': {
|
|
2533
2836
|
color: colors.rail.lighten(0.25),
|
|
2534
|
-
|
|
2837
|
+
minzoom: 14,
|
|
2838
|
+
size: { 14: 0, 15: 1, 20: 10 },
|
|
2839
|
+
lineDasharray: [2, 2],
|
|
2840
|
+
},
|
|
2841
|
+
// rail-service, lightrail-service
|
|
2842
|
+
'{tunnel-,bridge-,}transport-{rail,lightrail}-service:outline': {
|
|
2843
|
+
color: colors.rail,
|
|
2844
|
+
minzoom: 14,
|
|
2845
|
+
size: { 14: 0, 15: 1, 16: 1, 20: 14 },
|
|
2846
|
+
},
|
|
2847
|
+
'{tunnel-,bridge-,}transport-{rail,lightrail}-service': {
|
|
2848
|
+
color: colors.rail.lighten(0.25),
|
|
2849
|
+
minzoom: 15,
|
|
2850
|
+
size: { 15: 0, 16: 1, 20: 10 },
|
|
2535
2851
|
lineDasharray: [2, 2],
|
|
2536
2852
|
},
|
|
2537
2853
|
// subway
|
|
@@ -2707,7 +3023,7 @@ class Colorful extends StyleBuilder {
|
|
|
2707
3023
|
'marking-oneway{-reverse,}': {
|
|
2708
3024
|
minzoom: 16,
|
|
2709
3025
|
image: 'basics:marking-arrow',
|
|
2710
|
-
opacity: { 16: 0, 17: 0.
|
|
3026
|
+
opacity: { 16: 0, 17: 0.4, 20: 0.4 },
|
|
2711
3027
|
font: fonts.regular,
|
|
2712
3028
|
},
|
|
2713
3029
|
// TODO: bicycle and pedestrian
|
|
@@ -2983,6 +3299,14 @@ class Graybeard extends Colorful {
|
|
|
2983
3299
|
}
|
|
2984
3300
|
}
|
|
2985
3301
|
|
|
3302
|
+
class Shadow extends Colorful {
|
|
3303
|
+
name = 'Shadow';
|
|
3304
|
+
constructor() {
|
|
3305
|
+
super();
|
|
3306
|
+
this.transformDefaultColors(color => color.saturate(-1).invert().brightness(0.2));
|
|
3307
|
+
}
|
|
3308
|
+
}
|
|
3309
|
+
|
|
2986
3310
|
class Neutrino extends Colorful {
|
|
2987
3311
|
name = 'Neutrino';
|
|
2988
3312
|
defaultFonts = {
|
|
@@ -3402,6 +3726,7 @@ function getStyleBuilder(styleBuilder) {
|
|
|
3402
3726
|
const colorful = getStyleBuilder(Colorful);
|
|
3403
3727
|
const eclipse = getStyleBuilder(Eclipse);
|
|
3404
3728
|
const graybeard = getStyleBuilder(Graybeard);
|
|
3729
|
+
const shadow = getStyleBuilder(Shadow);
|
|
3405
3730
|
const neutrino = getStyleBuilder(Neutrino);
|
|
3406
3731
|
getStyleBuilder(Empty);
|
|
3407
3732
|
|
|
@@ -3492,6 +3817,147 @@ function isRasterTileJSONSpecification(spec) {
|
|
|
3492
3817
|
return true;
|
|
3493
3818
|
}
|
|
3494
3819
|
|
|
3820
|
+
let colorDictionary = new Map();
|
|
3821
|
+
function randomColor(options) {
|
|
3822
|
+
if (colorDictionary.size === 0)
|
|
3823
|
+
colorDictionary = initColorDictionary();
|
|
3824
|
+
options ??= {};
|
|
3825
|
+
let seed = inputToSeed(options.seed);
|
|
3826
|
+
const H = pickHue(options);
|
|
3827
|
+
const S = pickSaturation(H, options);
|
|
3828
|
+
const V = pickBrightness(H, S, options);
|
|
3829
|
+
return new HSV(H, S, V, options.opacity ?? 1);
|
|
3830
|
+
function pickHue(options) {
|
|
3831
|
+
return mod(randomWithin(getHueRange(options.hue)), 360);
|
|
3832
|
+
function getHueRange(hue) {
|
|
3833
|
+
if (typeof hue === 'number') {
|
|
3834
|
+
hue = mod(hue, 360);
|
|
3835
|
+
return [hue, hue];
|
|
3836
|
+
}
|
|
3837
|
+
if (typeof hue === 'string') {
|
|
3838
|
+
const color = colorDictionary.get(hue);
|
|
3839
|
+
if (color?.hueRange)
|
|
3840
|
+
return color.hueRange;
|
|
3841
|
+
}
|
|
3842
|
+
return [0, 360];
|
|
3843
|
+
}
|
|
3844
|
+
}
|
|
3845
|
+
function pickSaturation(hue, options) {
|
|
3846
|
+
if (options.hue === 'monochrome')
|
|
3847
|
+
return 0;
|
|
3848
|
+
if (options.luminosity === 'random')
|
|
3849
|
+
return randomWithin([0, 100]);
|
|
3850
|
+
let [sMin, sMax] = getColorInfo(hue).saturationRange;
|
|
3851
|
+
if (options.saturation === 'strong')
|
|
3852
|
+
return sMax;
|
|
3853
|
+
switch (options.luminosity) {
|
|
3854
|
+
case 'bright':
|
|
3855
|
+
sMin = 55;
|
|
3856
|
+
break;
|
|
3857
|
+
case 'dark':
|
|
3858
|
+
sMin = sMax - 10;
|
|
3859
|
+
break;
|
|
3860
|
+
case 'light':
|
|
3861
|
+
sMax = 55;
|
|
3862
|
+
break;
|
|
3863
|
+
}
|
|
3864
|
+
return randomWithin([sMin, sMax]);
|
|
3865
|
+
}
|
|
3866
|
+
function pickBrightness(h, s, options) {
|
|
3867
|
+
let bMin = getMinimumBrightness(h, s), bMax = 100;
|
|
3868
|
+
if (typeof options.luminosity === 'number') {
|
|
3869
|
+
bMin = options.luminosity;
|
|
3870
|
+
bMax = options.luminosity;
|
|
3871
|
+
}
|
|
3872
|
+
else {
|
|
3873
|
+
switch (options.luminosity) {
|
|
3874
|
+
case 'dark':
|
|
3875
|
+
bMax = Math.min(100, bMin + 20);
|
|
3876
|
+
break;
|
|
3877
|
+
case 'light':
|
|
3878
|
+
bMin = (bMax + bMin) / 2;
|
|
3879
|
+
break;
|
|
3880
|
+
case 'random':
|
|
3881
|
+
bMin = 0;
|
|
3882
|
+
bMax = 100;
|
|
3883
|
+
break;
|
|
3884
|
+
}
|
|
3885
|
+
}
|
|
3886
|
+
return randomWithin([bMin, bMax]);
|
|
3887
|
+
function getMinimumBrightness(h, s) {
|
|
3888
|
+
const { lowerBounds } = getColorInfo(h);
|
|
3889
|
+
for (let i = 0; i < lowerBounds.length - 1; i++) {
|
|
3890
|
+
const [s1, v1] = lowerBounds[i];
|
|
3891
|
+
const [s2, v2] = lowerBounds[i + 1];
|
|
3892
|
+
if (s >= s1 && s <= s2) {
|
|
3893
|
+
const m = (v2 - v1) / (s2 - s1), b = v1 - m * s1;
|
|
3894
|
+
return m * s + b;
|
|
3895
|
+
}
|
|
3896
|
+
}
|
|
3897
|
+
return 0;
|
|
3898
|
+
}
|
|
3899
|
+
}
|
|
3900
|
+
function randomWithin(range) {
|
|
3901
|
+
//Seeded random algorithm from http://indiegamr.com/generate-repeatable-random-numbers-in-js/
|
|
3902
|
+
seed = (seed * 9301 + 49297) % 233280;
|
|
3903
|
+
return Math.floor(range[0] + seed / 233280.0 * (range[1] - range[0]));
|
|
3904
|
+
}
|
|
3905
|
+
}
|
|
3906
|
+
function inputToSeed(input) {
|
|
3907
|
+
if (input == null)
|
|
3908
|
+
return 0;
|
|
3909
|
+
if (typeof input === 'number')
|
|
3910
|
+
return input;
|
|
3911
|
+
let i = 0;
|
|
3912
|
+
for (let p = 0; p < input.length; p++)
|
|
3913
|
+
i = (i * 0x101 + input.charCodeAt(p)) % 0x100000000;
|
|
3914
|
+
return i;
|
|
3915
|
+
}
|
|
3916
|
+
function initColorDictionary() {
|
|
3917
|
+
const dict = new Map();
|
|
3918
|
+
const defineColor = (name, hueRange, lowerBounds) => {
|
|
3919
|
+
const [greyest] = lowerBounds;
|
|
3920
|
+
const colorful = lowerBounds[lowerBounds.length - 1];
|
|
3921
|
+
dict.set(name, {
|
|
3922
|
+
hueRange,
|
|
3923
|
+
lowerBounds,
|
|
3924
|
+
saturationRange: [greyest[0], colorful[0]],
|
|
3925
|
+
brightnessRange: [colorful[1], greyest[1]],
|
|
3926
|
+
});
|
|
3927
|
+
};
|
|
3928
|
+
defineColor('monochrome', null, [[0, 0], [100, 0]]);
|
|
3929
|
+
defineColor('red', [-26, 18], [[20, 100], [30, 92], [40, 89], [50, 85], [60, 78], [70, 70], [80, 60], [90, 55], [100, 50]]);
|
|
3930
|
+
defineColor('orange', [18, 46], [[20, 100], [30, 93], [40, 88], [50, 86], [60, 85], [70, 70], [100, 70]]);
|
|
3931
|
+
defineColor('yellow', [46, 62], [[25, 100], [40, 94], [50, 89], [60, 86], [70, 84], [80, 82], [90, 80], [100, 75]]);
|
|
3932
|
+
defineColor('green', [62, 178], [[30, 100], [40, 90], [50, 85], [60, 81], [70, 74], [80, 64], [90, 50], [100, 40]]);
|
|
3933
|
+
defineColor('blue', [178, 257], [[20, 100], [30, 86], [40, 80], [50, 74], [60, 60], [70, 52], [80, 44], [90, 39], [100, 35]]);
|
|
3934
|
+
defineColor('purple', [257, 282], [[20, 100], [30, 87], [40, 79], [50, 70], [60, 65], [70, 59], [80, 52], [90, 45], [100, 42]]);
|
|
3935
|
+
defineColor('pink', [282, 334], [[20, 100], [30, 90], [40, 86], [60, 84], [80, 80], [90, 75], [100, 73]]);
|
|
3936
|
+
return dict;
|
|
3937
|
+
}
|
|
3938
|
+
function getColorInfo(hue) {
|
|
3939
|
+
hue = mod(hue, 360);
|
|
3940
|
+
if (hue >= 334)
|
|
3941
|
+
hue -= 360;
|
|
3942
|
+
for (const color of colorDictionary.values()) {
|
|
3943
|
+
if (color.hueRange && hue >= color.hueRange[0] && hue <= color.hueRange[1]) {
|
|
3944
|
+
return color;
|
|
3945
|
+
}
|
|
3946
|
+
}
|
|
3947
|
+
throw Error('Color hue value not found');
|
|
3948
|
+
}
|
|
3949
|
+
|
|
3950
|
+
/**
|
|
3951
|
+
* Generates a style specification based on the provided TileJSON specification and optional parameters.
|
|
3952
|
+
*
|
|
3953
|
+
* @param {TileJSONSpecification} tileJSON - The TileJSON specification to generate the style from.
|
|
3954
|
+
* @param {GuessStyleOptions} [options] - Optional parameters to customize the style generation.
|
|
3955
|
+
* @param {string} [options.baseUrl] - Base URL to resolve tile URLs.
|
|
3956
|
+
* @param {string} [options.glyphs] - URL template for glyphs.
|
|
3957
|
+
* @param {string} [options.sprite] - URL template for sprites.
|
|
3958
|
+
* @returns {StyleSpecification} The generated style specification.
|
|
3959
|
+
* @throws {Error} If the provided TileJSON specification is invalid.
|
|
3960
|
+
*/
|
|
3495
3961
|
function guessStyle(tileJSON, options) {
|
|
3496
3962
|
tileJSON = deepClone(tileJSON);
|
|
3497
3963
|
if (options && options.baseUrl) {
|
|
@@ -3537,6 +4003,23 @@ function getShortbreadStyle(spec, builderOption) {
|
|
|
3537
4003
|
sprite: builderOption.sprite,
|
|
3538
4004
|
});
|
|
3539
4005
|
}
|
|
4006
|
+
/**
|
|
4007
|
+
* Generates a Mapbox GL style specification based on the provided TileJSON vector specification.
|
|
4008
|
+
*
|
|
4009
|
+
* @param {TileJSONSpecificationVector} spec - The TileJSON vector specification containing vector layers.
|
|
4010
|
+
* @returns {StyleSpecification} The generated Mapbox GL style specification.
|
|
4011
|
+
*
|
|
4012
|
+
* This function creates a style specification with background, circle, line, and fill layers.
|
|
4013
|
+
* It assigns colors to the layers based on the vector layer IDs using predefined rules for hue, luminosity, and saturation.
|
|
4014
|
+
*
|
|
4015
|
+
* The resulting style specification includes:
|
|
4016
|
+
* - A white background layer.
|
|
4017
|
+
* - Circle layers for point features.
|
|
4018
|
+
* - Line layers for line features.
|
|
4019
|
+
* - Fill layers for polygon features.
|
|
4020
|
+
*
|
|
4021
|
+
* The source for the layers is created using the `sourceFromSpec` function with the provided vector specification.
|
|
4022
|
+
*/
|
|
3540
4023
|
function getInspectorStyle(spec) {
|
|
3541
4024
|
const sourceName = 'vectorSource';
|
|
3542
4025
|
const layers = { background: [], circle: [], line: [], fill: [] };
|
|
@@ -3561,7 +4044,7 @@ function getInspectorStyle(spec) {
|
|
|
3561
4044
|
saturation = 'strong';
|
|
3562
4045
|
luminosity = 'light';
|
|
3563
4046
|
}
|
|
3564
|
-
const color =
|
|
4047
|
+
const color = randomColor({
|
|
3565
4048
|
hue,
|
|
3566
4049
|
luminosity,
|
|
3567
4050
|
saturation,
|
|
@@ -3634,12 +4117,94 @@ function sourceFromSpec(spec, type) {
|
|
|
3634
4117
|
return source;
|
|
3635
4118
|
}
|
|
3636
4119
|
|
|
4120
|
+
/**
|
|
4121
|
+
* This library provides everything you need to build a map style.
|
|
4122
|
+
*
|
|
4123
|
+
* You can use it in the browser:
|
|
4124
|
+
* ```html
|
|
4125
|
+
* <html>
|
|
4126
|
+
* <head>
|
|
4127
|
+
* <script src="https://tiles.versatiles.org/assets/lib/versatiles-style/versatiles-style.js"></script>
|
|
4128
|
+
* </head>
|
|
4129
|
+
* <body>
|
|
4130
|
+
* <!-- ... -->
|
|
4131
|
+
* <script>
|
|
4132
|
+
* const style = VersatilesStyle.colorful();
|
|
4133
|
+
* // ...
|
|
4134
|
+
* </script>
|
|
4135
|
+
* </body>
|
|
4136
|
+
* </html>
|
|
4137
|
+
* ```
|
|
4138
|
+
*
|
|
4139
|
+
* or in Node.js:
|
|
4140
|
+
* ```shell
|
|
4141
|
+
* npm i @versatiles/style
|
|
4142
|
+
* ```
|
|
4143
|
+
* ```
|
|
4144
|
+
* import { colorful } from 'versatiles-style';
|
|
4145
|
+
* // OR: const { colorful } = require('versatiles-style');
|
|
4146
|
+
* const style = colorful();
|
|
4147
|
+
* ```
|
|
4148
|
+
*
|
|
4149
|
+
* You probably want to use one of the following functions:
|
|
4150
|
+
*
|
|
4151
|
+
* ---
|
|
4152
|
+
*
|
|
4153
|
+
* ## Generate a style for OpenStreetMap data:
|
|
4154
|
+
*
|
|
4155
|
+
* To generate a style from scratch you can use on of the prepared style functions:
|
|
4156
|
+
* - {@link colorful}
|
|
4157
|
+
* - {@link eclipse}
|
|
4158
|
+
* - {@link graybeard}
|
|
4159
|
+
* - {@link neutrino}
|
|
4160
|
+
* - {@link shadow}
|
|
4161
|
+
*
|
|
4162
|
+
* Each function accepts optional {@link StyleBuilderOptions} as argument to customize the style.
|
|
4163
|
+
*
|
|
4164
|
+
* Example:
|
|
4165
|
+
* ```
|
|
4166
|
+
* import { colorful } from 'versatiles-style';
|
|
4167
|
+
* const style = colorful({
|
|
4168
|
+
* baseUrl: 'https://tiles.example.org',
|
|
4169
|
+
* recolor: {
|
|
4170
|
+
* blend: 0.5,
|
|
4171
|
+
* blendColor: '#FFF', // make all colors lighter
|
|
4172
|
+
* }
|
|
4173
|
+
* });
|
|
4174
|
+
* ```
|
|
4175
|
+
*
|
|
4176
|
+
* ---
|
|
4177
|
+
*
|
|
4178
|
+
* ## Guess a style based on a TileJSON:
|
|
4179
|
+
*
|
|
4180
|
+
* To guess a style from a TileJSON you can use {@link guessStyle}.
|
|
4181
|
+
* This function needs a {@link TileJSONSpecification} and an optional {@link GuessStyleOptions} object.
|
|
4182
|
+
* Example:
|
|
4183
|
+
* ```
|
|
4184
|
+
* import { guessStyle } from 'versatiles-style';
|
|
4185
|
+
* const style = guessStyle(tilejson);
|
|
4186
|
+
* ```
|
|
4187
|
+
*
|
|
4188
|
+
* ---
|
|
4189
|
+
*
|
|
4190
|
+
* ## Please help us to improve this library:
|
|
4191
|
+
*
|
|
4192
|
+
* This library is used in quite some projects of the VersaTiles ecosystem but it is still in an early stage.
|
|
4193
|
+
* We are always looking for feedback, contributions, ideas, bug reports and help with the documentation.
|
|
4194
|
+
*
|
|
4195
|
+
* If you have any suggestions, please [open an issue](https://github.com/versatiles-org/versatiles-style/issues) or a pull request on [GitHub](https://github.com/versatiles-org/versatiles-style).
|
|
4196
|
+
*
|
|
4197
|
+
* If you want to know more about the VersaTiles project, please visit [versatiles.org](https://versatiles.org).
|
|
4198
|
+
*
|
|
4199
|
+
* @module
|
|
4200
|
+
*/
|
|
3637
4201
|
const styles = {
|
|
3638
4202
|
colorful,
|
|
3639
4203
|
eclipse,
|
|
3640
4204
|
graybeard,
|
|
4205
|
+
shadow,
|
|
3641
4206
|
neutrino,
|
|
3642
4207
|
};
|
|
3643
4208
|
|
|
3644
|
-
export { Color, colorful, eclipse, graybeard, guessStyle, neutrino, styles };
|
|
4209
|
+
export { Color, colorful, eclipse, graybeard, guessStyle, neutrino, shadow, styles };
|
|
3645
4210
|
//# sourceMappingURL=index.js.map
|