@versatiles/style 5.0.0 → 5.2.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/LICENSE +21 -0
- package/dist/browser.d.ts +2 -0
- package/dist/browser.js +2 -0
- package/dist/color/abstract.d.ts +32 -0
- package/dist/color/abstract.js +49 -0
- package/dist/color/hsl.d.ts +22 -0
- package/dist/color/hsl.js +101 -0
- package/dist/color/hsv.d.ts +18 -0
- package/dist/color/hsv.js +94 -0
- package/dist/color/index.d.ts +3 -0
- package/dist/color/index.js +27 -0
- package/dist/{guess_style/random_color.d.ts → color/random.d.ts} +2 -2
- package/dist/color/random.js +127 -0
- package/dist/color/rgb.d.ts +27 -0
- package/dist/color/rgb.js +213 -0
- package/dist/color/utils.d.ts +3 -0
- package/dist/color/utils.js +9 -0
- package/dist/guess_style/guess_style.js +3 -4
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/lib/utils.js +3 -4
- package/dist/shortbread/layers.js +14 -3
- package/dist/style_builder/decorator.d.ts +1 -1
- package/dist/style_builder/decorator.js +3 -4
- package/dist/style_builder/recolor.d.ts +2 -1
- package/dist/style_builder/recolor.js +15 -49
- package/dist/style_builder/style_builder.d.ts +1 -1
- package/dist/style_builder/style_builder.js +8 -5
- package/dist/style_builder/types.d.ts +1 -1
- package/dist/styles/colorful.js +49 -8
- package/dist/styles/eclipse.js +1 -4
- package/dist/styles/graybeard.js +1 -1
- package/dist/styles/neutrino.js +6 -6
- package/package.json +15 -17
- package/dist/guess_style/random_color.js +0 -148
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { HSL } from './hsl.js';
|
|
2
|
+
import { HSV } from './hsv.js';
|
|
3
|
+
import { Color } from './abstract.js';
|
|
4
|
+
import { clamp, formatFloat } from './utils.js';
|
|
5
|
+
export class RGB extends Color {
|
|
6
|
+
r = 0; // between 0 and 255
|
|
7
|
+
g = 0; // between 0 and 255
|
|
8
|
+
b = 0; // between 0 and 255
|
|
9
|
+
a = 1; // between 0 and 1
|
|
10
|
+
constructor(r, g, b, a = 1) {
|
|
11
|
+
super();
|
|
12
|
+
this.r = clamp(r, 0, 255);
|
|
13
|
+
this.g = clamp(g, 0, 255);
|
|
14
|
+
this.b = clamp(b, 0, 255);
|
|
15
|
+
this.a = clamp(a, 0, 1);
|
|
16
|
+
}
|
|
17
|
+
clone() {
|
|
18
|
+
return new RGB(this.r, this.g, this.b, this.a);
|
|
19
|
+
}
|
|
20
|
+
asArray() {
|
|
21
|
+
return [this.r, this.g, this.b, this.a];
|
|
22
|
+
}
|
|
23
|
+
asString() {
|
|
24
|
+
if (this.a === 1) {
|
|
25
|
+
return `rgb(${this.r.toFixed(0)},${this.g.toFixed(0)},${this.b.toFixed(0)})`;
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
return `rgba(${this.r.toFixed(0)},${this.g.toFixed(0)},${this.b.toFixed(0)},${formatFloat(this.a, 3)})`;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
asHex() {
|
|
32
|
+
const r = Math.round(this.r).toString(16).padStart(2, '0');
|
|
33
|
+
const g = Math.round(this.g).toString(16).padStart(2, '0');
|
|
34
|
+
const b = Math.round(this.b).toString(16).padStart(2, '0');
|
|
35
|
+
if (this.a === 1) {
|
|
36
|
+
return `#${r}${g}${b}`.toUpperCase();
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
const a = Math.round(this.a * 255).toString(16).padStart(2, '0');
|
|
40
|
+
return `#${r}${g}${b}${a}`.toUpperCase();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
asHSL() {
|
|
44
|
+
const r = this.r / 255;
|
|
45
|
+
const g = this.g / 255;
|
|
46
|
+
const b = this.b / 255;
|
|
47
|
+
const min = Math.min(r, g, b);
|
|
48
|
+
const max = Math.max(r, g, b);
|
|
49
|
+
const delta = max - min;
|
|
50
|
+
let h = 0;
|
|
51
|
+
let s = 0;
|
|
52
|
+
if (max === min)
|
|
53
|
+
h = 0;
|
|
54
|
+
else if (r === max)
|
|
55
|
+
h = (g - b) / delta;
|
|
56
|
+
else if (g === max)
|
|
57
|
+
h = 2 + (b - r) / delta;
|
|
58
|
+
else if (b === max)
|
|
59
|
+
h = 4 + (r - g) / delta;
|
|
60
|
+
h = Math.min(h * 60, 360);
|
|
61
|
+
if (h < 0)
|
|
62
|
+
h += 360;
|
|
63
|
+
const l = (min + max) / 2;
|
|
64
|
+
if (max === min)
|
|
65
|
+
s = 0;
|
|
66
|
+
else if (l <= 0.5)
|
|
67
|
+
s = delta / (max + min);
|
|
68
|
+
else
|
|
69
|
+
s = delta / (2 - max - min);
|
|
70
|
+
return new HSL(h, s * 100, l * 100, this.a);
|
|
71
|
+
}
|
|
72
|
+
;
|
|
73
|
+
asHSV() {
|
|
74
|
+
const r = this.r / 255;
|
|
75
|
+
const g = this.g / 255;
|
|
76
|
+
const b = this.b / 255;
|
|
77
|
+
const v = Math.max(r, g, b);
|
|
78
|
+
const diff = v - Math.min(r, g, b);
|
|
79
|
+
let h = 0;
|
|
80
|
+
let s = 0;
|
|
81
|
+
if (diff !== 0) {
|
|
82
|
+
function diffc(c) {
|
|
83
|
+
return (v - c) / 6 / diff + 1 / 2;
|
|
84
|
+
}
|
|
85
|
+
;
|
|
86
|
+
s = diff / v;
|
|
87
|
+
const rdif = diffc(r);
|
|
88
|
+
const gdif = diffc(g);
|
|
89
|
+
const bdif = diffc(b);
|
|
90
|
+
if (r === v)
|
|
91
|
+
h = bdif - gdif;
|
|
92
|
+
else if (g === v)
|
|
93
|
+
h = (1 / 3) + rdif - bdif;
|
|
94
|
+
else if (b === v)
|
|
95
|
+
h = (2 / 3) + gdif - rdif;
|
|
96
|
+
if (h < 0)
|
|
97
|
+
h += 1;
|
|
98
|
+
else if (h > 1)
|
|
99
|
+
h -= 1;
|
|
100
|
+
}
|
|
101
|
+
return new HSV(h * 360, s * 100, v * 100, this.a);
|
|
102
|
+
}
|
|
103
|
+
asRGB() {
|
|
104
|
+
return this.clone();
|
|
105
|
+
}
|
|
106
|
+
toRGB() {
|
|
107
|
+
return this;
|
|
108
|
+
}
|
|
109
|
+
static parse(str) {
|
|
110
|
+
str = str.toLowerCase().replaceAll(/[^0-9a-z.#,()]/g, '');
|
|
111
|
+
let match;
|
|
112
|
+
match = str.match(/^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})?$/);
|
|
113
|
+
if (match) {
|
|
114
|
+
const r = parseInt(match[1], 16);
|
|
115
|
+
const g = parseInt(match[2], 16);
|
|
116
|
+
const b = parseInt(match[3], 16);
|
|
117
|
+
const a = match[4] ? parseInt(match[4], 16) / 255 : 1;
|
|
118
|
+
return new RGB(r, g, b, a);
|
|
119
|
+
}
|
|
120
|
+
match = str.match(/^#([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])?$/);
|
|
121
|
+
if (match) {
|
|
122
|
+
const r = parseInt(match[1], 16) * 17;
|
|
123
|
+
const g = parseInt(match[2], 16) * 17;
|
|
124
|
+
const b = parseInt(match[3], 16) * 17;
|
|
125
|
+
const a = match[4] ? parseInt(match[4], 16) / 15 : 1;
|
|
126
|
+
return new RGB(r, g, b, a);
|
|
127
|
+
}
|
|
128
|
+
str = str.trim().toLowerCase().replaceAll(' ', '');
|
|
129
|
+
match = str.match(/^rgb\((\d+),(\d+),(\d+)\)$/);
|
|
130
|
+
if (match) {
|
|
131
|
+
const r = parseInt(match[1]);
|
|
132
|
+
const g = parseInt(match[2]);
|
|
133
|
+
const b = parseInt(match[3]);
|
|
134
|
+
return new RGB(r, g, b);
|
|
135
|
+
}
|
|
136
|
+
match = str.match(/^rgba\((\d+),(\d+),(\d+),([.\d]+)\)$/);
|
|
137
|
+
if (match) {
|
|
138
|
+
const r = parseInt(match[1]);
|
|
139
|
+
const g = parseInt(match[2]);
|
|
140
|
+
const b = parseInt(match[3]);
|
|
141
|
+
const a = parseFloat(match[4]);
|
|
142
|
+
return new RGB(r, g, b, a);
|
|
143
|
+
}
|
|
144
|
+
throw new Error(`Invalid RGB color string: "${str}"`);
|
|
145
|
+
}
|
|
146
|
+
gamma(value) {
|
|
147
|
+
if (value < 1e-3)
|
|
148
|
+
value = 1e-3;
|
|
149
|
+
if (value > 1e3)
|
|
150
|
+
value = 1e3;
|
|
151
|
+
this.r = Math.pow(this.r / 255, value) * 255;
|
|
152
|
+
this.g = Math.pow(this.g / 255, value) * 255;
|
|
153
|
+
this.b = Math.pow(this.b / 255, value) * 255;
|
|
154
|
+
return this;
|
|
155
|
+
}
|
|
156
|
+
invert() {
|
|
157
|
+
this.r = 255 - this.r;
|
|
158
|
+
this.g = 255 - this.g;
|
|
159
|
+
this.b = 255 - this.b;
|
|
160
|
+
return this;
|
|
161
|
+
}
|
|
162
|
+
contrast(value) {
|
|
163
|
+
if (value < 0)
|
|
164
|
+
value = 0;
|
|
165
|
+
if (value > 1e6)
|
|
166
|
+
value = 1e6;
|
|
167
|
+
this.r = clamp((this.r - 127.5) * value + 127.5, 0, 255);
|
|
168
|
+
this.g = clamp((this.g - 127.5) * value + 127.5, 0, 255);
|
|
169
|
+
this.b = clamp((this.b - 127.5) * value + 127.5, 0, 255);
|
|
170
|
+
return this;
|
|
171
|
+
}
|
|
172
|
+
brightness(value) {
|
|
173
|
+
if (value < -1)
|
|
174
|
+
value = -1;
|
|
175
|
+
if (value > 1)
|
|
176
|
+
value = 1;
|
|
177
|
+
const a = 1 - Math.abs(value);
|
|
178
|
+
const b = (value < 0) ? 0 : 255 * value;
|
|
179
|
+
this.r = this.r * a + b;
|
|
180
|
+
this.g = this.g * a + b;
|
|
181
|
+
this.b = this.b * a + b;
|
|
182
|
+
return this;
|
|
183
|
+
}
|
|
184
|
+
tint(value, tintColor) {
|
|
185
|
+
if (value < 0)
|
|
186
|
+
value = 0;
|
|
187
|
+
if (value > 1)
|
|
188
|
+
value = 1;
|
|
189
|
+
const hsv = this.asHSV();
|
|
190
|
+
hsv.h = tintColor.toHSV().h;
|
|
191
|
+
const rgbNew = hsv.toRGB();
|
|
192
|
+
rgbNew.r = this.r * (1 - value) + value * rgbNew.r;
|
|
193
|
+
rgbNew.g = this.g * (1 - value) + value * rgbNew.g;
|
|
194
|
+
rgbNew.b = this.b * (1 - value) + value * rgbNew.b;
|
|
195
|
+
return rgbNew;
|
|
196
|
+
}
|
|
197
|
+
lighten(ratio) {
|
|
198
|
+
this.r = clamp(255 - (255 - this.r) * (1 - ratio), 0, 255);
|
|
199
|
+
this.g = clamp(255 - (255 - this.g) * (1 - ratio), 0, 255);
|
|
200
|
+
this.b = clamp(255 - (255 - this.b) * (1 - ratio), 0, 255);
|
|
201
|
+
return this;
|
|
202
|
+
}
|
|
203
|
+
darken(ratio) {
|
|
204
|
+
this.r = clamp(this.r * (1 - ratio), 0, 255);
|
|
205
|
+
this.g = clamp(this.g * (1 - ratio), 0, 255);
|
|
206
|
+
this.b = clamp(this.b * (1 - ratio), 0, 255);
|
|
207
|
+
return this;
|
|
208
|
+
}
|
|
209
|
+
fade(value) {
|
|
210
|
+
this.a *= 1 - value;
|
|
211
|
+
return this;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export function clamp(num, min, max) {
|
|
2
|
+
return Math.min(Math.max(min, num), max);
|
|
3
|
+
}
|
|
4
|
+
export function mod(num, max) {
|
|
5
|
+
return ((num % max) + max) % max;
|
|
6
|
+
}
|
|
7
|
+
export function formatFloat(num, precision) {
|
|
8
|
+
return num.toFixed(precision).replace(/0+$/, '').replace(/\.$/, '');
|
|
9
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { isTileJSONSpecification, isVectorLayers } from '../types/index.js';
|
|
2
2
|
import { resolveUrl } from '../lib/utils.js';
|
|
3
|
-
import randomColorGenerator from './random_color.js';
|
|
4
3
|
import { colorful } from '../styles/index.js';
|
|
4
|
+
import { Color } from '../color/index.js';
|
|
5
5
|
export function guessStyle(opt) {
|
|
6
6
|
const { format } = opt;
|
|
7
7
|
const tilejsonBasic = {
|
|
@@ -131,7 +131,6 @@ function getInspectorStyle(spec) {
|
|
|
131
131
|
const sourceName = 'vectorSource';
|
|
132
132
|
const layers = { background: [], circle: [], line: [], fill: [] };
|
|
133
133
|
layers.background.push({ 'id': 'background', 'type': 'background', 'paint': { 'background-color': '#fff' } });
|
|
134
|
-
const randomColor = randomColorGenerator();
|
|
135
134
|
spec.vector_layers.forEach((vector_layer) => {
|
|
136
135
|
let luminosity = 'bright', saturation, hue;
|
|
137
136
|
if (/water|ocean|lake|sea|river/.test(vector_layer.id))
|
|
@@ -152,13 +151,13 @@ function getInspectorStyle(spec) {
|
|
|
152
151
|
saturation = 'strong';
|
|
153
152
|
luminosity = 'light';
|
|
154
153
|
}
|
|
155
|
-
const color =
|
|
154
|
+
const color = Color.random({
|
|
156
155
|
hue,
|
|
157
156
|
luminosity,
|
|
158
157
|
saturation,
|
|
159
158
|
seed: vector_layer.id,
|
|
160
159
|
opacity: 0.6,
|
|
161
|
-
});
|
|
160
|
+
}).asString();
|
|
162
161
|
layers.circle.push({
|
|
163
162
|
id: `${sourceName}-${vector_layer.id}-circle`,
|
|
164
163
|
'source-layer': vector_layer.id,
|
package/dist/index.d.ts
CHANGED
|
@@ -3,3 +3,4 @@ export * from './styles/index.js';
|
|
|
3
3
|
export { guessStyle, guessStyleFromContainer } from './guess_style/index.js';
|
|
4
4
|
export type { GuessStyleOptions, GuessContainerOptions } from './guess_style/index.js';
|
|
5
5
|
export type { VectorLayer } from './types/index.js';
|
|
6
|
+
export { default as Color } from './color/index.js';
|
package/dist/index.js
CHANGED
package/dist/lib/utils.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import Color from 'color';
|
|
1
|
+
import Color from '../color/index.js';
|
|
2
2
|
// Utility function to deep clone an object
|
|
3
3
|
export function deepClone(obj) {
|
|
4
4
|
const type = typeof obj;
|
|
@@ -21,8 +21,7 @@ export function deepClone(obj) {
|
|
|
21
21
|
return obj.map((e) => deepClone(e));
|
|
22
22
|
}
|
|
23
23
|
if (obj instanceof Color) {
|
|
24
|
-
|
|
25
|
-
return Color(obj);
|
|
24
|
+
return obj.clone();
|
|
26
25
|
}
|
|
27
26
|
if (obj == null)
|
|
28
27
|
return obj;
|
|
@@ -83,7 +82,7 @@ export function deepMerge(source0, ...sources) {
|
|
|
83
82
|
}
|
|
84
83
|
if (sourceValue instanceof Color) {
|
|
85
84
|
// @ts-expect-error: Too complicated to handle
|
|
86
|
-
target[key] =
|
|
85
|
+
target[key] = sourceValue.clone();
|
|
87
86
|
continue;
|
|
88
87
|
}
|
|
89
88
|
if (isSimpleObject(target[key]) && isSimpleObject(sourceValue)) {
|
|
@@ -110,29 +110,40 @@ export function getShortbreadLayers(option) {
|
|
|
110
110
|
...['tunnel', 'street', 'bridge'].flatMap((c) => {
|
|
111
111
|
let filter;
|
|
112
112
|
let prefix;
|
|
113
|
+
let suffixes = [];
|
|
113
114
|
const results = [];
|
|
114
115
|
switch (c) {
|
|
115
116
|
case 'tunnel':
|
|
116
117
|
filter = [['==', 'tunnel', true]];
|
|
117
118
|
prefix = 'tunnel-';
|
|
119
|
+
suffixes = [':outline', ''];
|
|
118
120
|
break;
|
|
119
121
|
case 'street':
|
|
120
122
|
filter = [['!=', 'bridge', true], ['!=', 'tunnel', true]];
|
|
121
123
|
prefix = '';
|
|
124
|
+
suffixes = [':outline', ''];
|
|
122
125
|
break;
|
|
123
126
|
case 'bridge':
|
|
124
127
|
filter = [['==', 'bridge', true]];
|
|
125
128
|
prefix = 'bridge-';
|
|
129
|
+
suffixes = [':bridge', ':outline', ''];
|
|
126
130
|
break;
|
|
127
131
|
}
|
|
128
|
-
// bridges
|
|
129
|
-
|
|
132
|
+
// in osm data streets on bridges are often not tagged as such
|
|
133
|
+
// to be able to have multiple levels of bridges cross over each
|
|
134
|
+
// other in the right order without using a secondary property.
|
|
135
|
+
// this results in bridge-polygons being rendered above streets.
|
|
136
|
+
// therefore bridge polygons are *under* surface streets here.
|
|
137
|
+
// this workaround is also wrong, but everyone is using it since
|
|
138
|
+
// it's simpler than removing all these tagging hacks from osm.
|
|
139
|
+
// bridges, above tunnel, below street
|
|
140
|
+
if (c === 'street')
|
|
130
141
|
results.push({
|
|
131
142
|
id: 'bridge',
|
|
132
143
|
type: 'fill',
|
|
133
144
|
'source-layer': 'bridges',
|
|
134
145
|
});
|
|
135
|
-
|
|
146
|
+
suffixes.forEach(suffix => {
|
|
136
147
|
// pedestrian zone — no outline
|
|
137
148
|
if (suffix === ':outline')
|
|
138
149
|
results.push({
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { MaplibreLayer } from '../types/index.js';
|
|
2
2
|
import type { StyleRules } from './types.js';
|
|
3
|
-
import type { CachedRecolor } from './recolor.
|
|
3
|
+
import type { CachedRecolor } from './recolor.js';
|
|
4
4
|
export declare function decorate(layers: MaplibreLayer[], rules: StyleRules, recolor: CachedRecolor): MaplibreLayer[];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import Color from 'color';
|
|
1
|
+
import Color from '../color/index.js';
|
|
2
2
|
import expandBraces from 'brace-expansion';
|
|
3
3
|
import maplibreProperties from '../shortbread/properties.js';
|
|
4
4
|
import { deepMerge } from '../lib/utils.js';
|
|
@@ -93,11 +93,10 @@ export function decorate(layers, rules, recolor) {
|
|
|
93
93
|
}
|
|
94
94
|
function processColor(value) {
|
|
95
95
|
if (typeof value === 'string')
|
|
96
|
-
value = Color(value);
|
|
96
|
+
value = Color.parse(value);
|
|
97
97
|
if (value instanceof Color) {
|
|
98
98
|
const color = recolor.do(value);
|
|
99
|
-
|
|
100
|
-
return text.toLowerCase();
|
|
99
|
+
return color.asString();
|
|
101
100
|
}
|
|
102
101
|
throw new Error(`unknown color type "${typeof value}"`);
|
|
103
102
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import Color from 'color';
|
|
1
|
+
import Color from '../color/index.js';
|
|
2
2
|
export interface RecolorOptions {
|
|
3
3
|
invertBrightness?: boolean;
|
|
4
4
|
rotate?: number;
|
|
@@ -11,6 +11,7 @@ export interface RecolorOptions {
|
|
|
11
11
|
}
|
|
12
12
|
export declare function getDefaultRecolorFlags(): RecolorOptions;
|
|
13
13
|
export declare function recolorObject(colors: Record<string, Color>, opt?: RecolorOptions): void;
|
|
14
|
+
export declare function recolorArray(colors: Color[], opt?: RecolorOptions): void;
|
|
14
15
|
export declare class CachedRecolor {
|
|
15
16
|
private readonly skip;
|
|
16
17
|
private readonly opt?;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import Color from 'color';
|
|
1
|
+
import Color from '../color/index.js';
|
|
2
2
|
export function getDefaultRecolorFlags() {
|
|
3
3
|
return {
|
|
4
4
|
invertBrightness: false,
|
|
@@ -39,6 +39,13 @@ export function recolorObject(colors, opt) {
|
|
|
39
39
|
colors[k] = recolor(c, opt);
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
|
+
export function recolorArray(colors, opt) {
|
|
43
|
+
if (!isValidRecolorOptions(opt))
|
|
44
|
+
return;
|
|
45
|
+
for (let i = 0; i < colors.length; i++) {
|
|
46
|
+
colors[i] = recolor(colors[i], opt);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
42
49
|
export class CachedRecolor {
|
|
43
50
|
skip;
|
|
44
51
|
opt;
|
|
@@ -51,7 +58,7 @@ export class CachedRecolor {
|
|
|
51
58
|
do(color) {
|
|
52
59
|
if (this.skip)
|
|
53
60
|
return color;
|
|
54
|
-
const key = color.
|
|
61
|
+
const key = color.asHex();
|
|
55
62
|
const result = this.cache.get(key);
|
|
56
63
|
if (result)
|
|
57
64
|
return result;
|
|
@@ -64,59 +71,18 @@ export function recolor(color, opt) {
|
|
|
64
71
|
if (!isValidRecolorOptions(opt))
|
|
65
72
|
return color;
|
|
66
73
|
if (opt.invertBrightness ?? false)
|
|
67
|
-
color =
|
|
74
|
+
color = color.invertLuminosity();
|
|
68
75
|
if ((opt.rotate !== undefined) && (opt.rotate !== 0))
|
|
69
|
-
color = color.
|
|
76
|
+
color = color.rotateHue(opt.rotate);
|
|
70
77
|
if ((opt.saturate !== undefined) && (opt.saturate !== 0))
|
|
71
78
|
color = color.saturate(opt.saturate);
|
|
72
79
|
if ((opt.gamma !== undefined) && (opt.gamma !== 1))
|
|
73
|
-
color = gamma(
|
|
80
|
+
color = color.gamma(opt.gamma);
|
|
74
81
|
if ((opt.contrast !== undefined) && (opt.contrast !== 1))
|
|
75
|
-
color = contrast(
|
|
82
|
+
color = color.contrast(opt.contrast);
|
|
76
83
|
if ((opt.brightness !== undefined) && (opt.brightness !== 0))
|
|
77
|
-
color = brightness(
|
|
84
|
+
color = color.brightness(opt.brightness);
|
|
78
85
|
if ((opt.tint !== undefined) && (opt.tintColor !== undefined) && (opt.tint !== 0))
|
|
79
|
-
color = tint(
|
|
86
|
+
color = color.tint(opt.tint, Color.parse(opt.tintColor));
|
|
80
87
|
return color;
|
|
81
|
-
function invert(c) {
|
|
82
|
-
c = c.hsl();
|
|
83
|
-
return c.lightness(100 - c.lightness()).rgb();
|
|
84
|
-
}
|
|
85
|
-
function gamma(c, value) {
|
|
86
|
-
if (value < 1e-3)
|
|
87
|
-
value = 1e-3;
|
|
88
|
-
if (value > 1e3)
|
|
89
|
-
value = 1e3;
|
|
90
|
-
const rgb = c.rgb().array();
|
|
91
|
-
return Color.rgb(Math.pow(rgb[0] / 255, value) * 255, Math.pow(rgb[1] / 255, value) * 255, Math.pow(rgb[2] / 255, value) * 255, c.alpha());
|
|
92
|
-
}
|
|
93
|
-
function contrast(c, value) {
|
|
94
|
-
if (value < 0)
|
|
95
|
-
value = 0;
|
|
96
|
-
if (value > 1e6)
|
|
97
|
-
value = 1e6;
|
|
98
|
-
const rgb = c.rgb().array();
|
|
99
|
-
return Color.rgb((rgb[0] - 127.5) * value + 127.5, (rgb[1] - 127.5) * value + 127.5, (rgb[2] - 127.5) * value + 127.5, c.alpha());
|
|
100
|
-
}
|
|
101
|
-
function brightness(c, value) {
|
|
102
|
-
if (value < -1e6)
|
|
103
|
-
value = -1e6;
|
|
104
|
-
if (value > 1e6)
|
|
105
|
-
value = 1e6;
|
|
106
|
-
const a = 1 - Math.abs(value);
|
|
107
|
-
const b = (value < 0) ? 0 : 255 * value;
|
|
108
|
-
const rgb = c.rgb().array();
|
|
109
|
-
return Color.rgb(rgb[0] * a + b, rgb[1] * a + b, rgb[2] * a + b, c.alpha());
|
|
110
|
-
}
|
|
111
|
-
function tint(c, value, tintColor) {
|
|
112
|
-
if (value < 0)
|
|
113
|
-
value = 0;
|
|
114
|
-
if (value > 1)
|
|
115
|
-
value = 1;
|
|
116
|
-
const rgb0 = c.rgb().array();
|
|
117
|
-
const hsv = c.hsv().array();
|
|
118
|
-
hsv[0] = tintColor.hue();
|
|
119
|
-
const rgbNew = Color.hsv(hsv).rgb().array();
|
|
120
|
-
return Color.rgb(rgb0[0] * (1 - value) + value * rgbNew[0], rgb0[1] * (1 - value) + value * rgbNew[1], rgb0[2] * (1 - value) + value * rgbNew[2], c.alpha());
|
|
121
|
-
}
|
|
122
88
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import Color from 'color';
|
|
1
|
+
import Color from '../color/index.js';
|
|
2
2
|
import type { MaplibreStyle } from '../types/maplibre.js';
|
|
3
3
|
import type { StyleBuilderColorStrings, StyleBuilderColors, StyleBuilderFontStrings, StyleBuilderOptions } from './types.js';
|
|
4
4
|
import type { StyleRules, StyleRulesOptions } from './types.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import Color from 'color';
|
|
1
|
+
import Color from '../color/index.js';
|
|
2
2
|
import { getShortbreadTemplate, getShortbreadLayers } from '../shortbread/index.js';
|
|
3
3
|
import { decorate } from './decorator.js';
|
|
4
4
|
import { CachedRecolor, getDefaultRecolorFlags } from './recolor.js';
|
|
@@ -17,8 +17,11 @@ export default class StyleBuilder {
|
|
|
17
17
|
const recolorOptions = options.recolor ?? getDefaultRecolorFlags();
|
|
18
18
|
const colors = this.getColors(this.defaultColors);
|
|
19
19
|
if (options.colors) {
|
|
20
|
-
for (const key in options.colors)
|
|
21
|
-
|
|
20
|
+
for (const key in options.colors) {
|
|
21
|
+
const value = options.colors[key];
|
|
22
|
+
if (value != null)
|
|
23
|
+
colors[key] = Color.parse(value);
|
|
24
|
+
}
|
|
22
25
|
}
|
|
23
26
|
const fonts = deepClone(this.defaultFonts);
|
|
24
27
|
if (options.fonts) {
|
|
@@ -74,7 +77,7 @@ export default class StyleBuilder {
|
|
|
74
77
|
}
|
|
75
78
|
getColors(colors) {
|
|
76
79
|
const entriesString = Object.entries(colors);
|
|
77
|
-
const entriesColor = entriesString.map(([key, value]) => [key, Color(value)]);
|
|
80
|
+
const entriesColor = entriesString.map(([key, value]) => [key, Color.parse(value)]);
|
|
78
81
|
const result = Object.fromEntries(entriesColor);
|
|
79
82
|
return result;
|
|
80
83
|
}
|
|
@@ -94,7 +97,7 @@ export default class StyleBuilder {
|
|
|
94
97
|
transformDefaultColors(callback) {
|
|
95
98
|
const colors = this.getColors(this.defaultColors);
|
|
96
99
|
for (const key in colors) {
|
|
97
|
-
this.defaultColors[key] = callback(colors[key]).
|
|
100
|
+
this.defaultColors[key] = callback(colors[key]).asHex();
|
|
98
101
|
}
|
|
99
102
|
}
|
|
100
103
|
}
|
package/dist/styles/colorful.js
CHANGED
|
@@ -317,6 +317,47 @@ export default class Colorful extends StyleBuilder {
|
|
|
317
317
|
'bridge-{street,way}-*:outline': {
|
|
318
318
|
lineCap: 'butt',
|
|
319
319
|
},
|
|
320
|
+
// faux bridges
|
|
321
|
+
'bridge-{street,way}-*:bridge': {
|
|
322
|
+
lineCap: 'butt',
|
|
323
|
+
lineJoin: 'round',
|
|
324
|
+
color: colors.land.darken(0.02),
|
|
325
|
+
fillAntialias: true,
|
|
326
|
+
opacity: 0.5,
|
|
327
|
+
},
|
|
328
|
+
'bridge-street-motorway:bridge': {
|
|
329
|
+
size: { '5': 0, '6': 3, '10': 7, '14': 7, '16': 20, '18': 53, '19': 118, '20': 235 }
|
|
330
|
+
},
|
|
331
|
+
'bridge-street-trunk:bridge': {
|
|
332
|
+
size: { '7': 0, '8': 3, '10': 6, '14': 8, '16': 17, '18': 50, '19': 104, '20': 202 }
|
|
333
|
+
},
|
|
334
|
+
'bridge-street-primary:bridge': {
|
|
335
|
+
size: { '8': 0, '9': 1, '10': 6, '14': 8, '16': 17, '18': 50, '19': 104, '20': 202 }
|
|
336
|
+
},
|
|
337
|
+
'bridge-street-secondary:bridge': {
|
|
338
|
+
size: { '11': 3, '14': 7, '16': 11, '18': 42, '19': 95, '20': 193 },
|
|
339
|
+
opacity: { '11': 0, '12': 1 }
|
|
340
|
+
},
|
|
341
|
+
'bridge-street-motorway-link:bridge': {
|
|
342
|
+
minzoom: 12,
|
|
343
|
+
size: { '12': 3, '14': 4, '16': 10, '18': 20, '20': 56 }
|
|
344
|
+
},
|
|
345
|
+
'bridge-street-{trunk,primary,secondary}-link:bridge': {
|
|
346
|
+
minzoom: 13,
|
|
347
|
+
size: { '12': 3, '14': 4, '16': 10, '18': 20, '20': 56 }
|
|
348
|
+
},
|
|
349
|
+
'bridge-street-{tertiary,tertiary-link,unclassified,residential,livingstreet,pedestrian}*:bridge': {
|
|
350
|
+
size: { '12': 3, '14': 4, '16': 8, '18': 36, '19': 90, '20': 179 },
|
|
351
|
+
opacity: { '12': 0, '13': 1 }
|
|
352
|
+
},
|
|
353
|
+
'bridge-street-{service,track}:bridge': {
|
|
354
|
+
size: { '14': 3, '16': 6, '18': 25, '19': 67, '20': 134 },
|
|
355
|
+
opacity: { '14': 0, '15': 1 }
|
|
356
|
+
},
|
|
357
|
+
'bridge-way-*:bridge': {
|
|
358
|
+
size: { '15': 0, '16': 7, '18': 10, '19': 17, '20': 31 },
|
|
359
|
+
minzoom: 15
|
|
360
|
+
},
|
|
320
361
|
// special color: motorway
|
|
321
362
|
'{bridge-,}street-motorway{-link,}:outline': {
|
|
322
363
|
color: colors.motorwaybg,
|
|
@@ -435,10 +476,10 @@ export default class Colorful extends StyleBuilder {
|
|
|
435
476
|
color: colors.foot.lighten(0.02),
|
|
436
477
|
},
|
|
437
478
|
'tunnel-way-{footway,path,steps}:outline': {
|
|
438
|
-
color: colors.foot.darken(0.1).
|
|
479
|
+
color: colors.foot.darken(0.1).saturate(-0.5),
|
|
439
480
|
},
|
|
440
481
|
'tunnel-way-{footway,path,steps}': {
|
|
441
|
-
color: colors.foot.darken(0.02).
|
|
482
|
+
color: colors.foot.darken(0.02).saturate(-0.5),
|
|
442
483
|
lineDasharray: [1, 0.2],
|
|
443
484
|
},
|
|
444
485
|
// cycleway
|
|
@@ -449,10 +490,10 @@ export default class Colorful extends StyleBuilder {
|
|
|
449
490
|
color: colors.cycle,
|
|
450
491
|
},
|
|
451
492
|
'tunnel-way-cycleway:outline': {
|
|
452
|
-
color: colors.cycle.darken(0.1).
|
|
493
|
+
color: colors.cycle.darken(0.1).saturate(-0.5),
|
|
453
494
|
},
|
|
454
495
|
'tunnel-way-cycleway': {
|
|
455
|
-
color: colors.cycle.darken(0.02).
|
|
496
|
+
color: colors.cycle.darken(0.02).saturate(-0.5),
|
|
456
497
|
lineDasharray: [1, 0.2],
|
|
457
498
|
},
|
|
458
499
|
// cycle streets overlay
|
|
@@ -567,7 +608,7 @@ export default class Colorful extends StyleBuilder {
|
|
|
567
608
|
size: { 5: 8, 8: 12 },
|
|
568
609
|
},
|
|
569
610
|
'label-place-*': {
|
|
570
|
-
color: colors.label.
|
|
611
|
+
color: colors.label.rotateHue(-15).saturate(1).darken(0.05),
|
|
571
612
|
font: fonts.regular,
|
|
572
613
|
textHaloColor: colors.labelHalo,
|
|
573
614
|
textHaloWidth: 2,
|
|
@@ -602,19 +643,19 @@ export default class Colorful extends StyleBuilder {
|
|
|
602
643
|
minzoom: 11,
|
|
603
644
|
size: { 11: 11, 13: 14 },
|
|
604
645
|
textTransform: 'uppercase',
|
|
605
|
-
color: colors.label.
|
|
646
|
+
color: colors.label.rotateHue(-30).saturate(1).darken(0.05),
|
|
606
647
|
},
|
|
607
648
|
'label-place-quarter': {
|
|
608
649
|
minzoom: 13,
|
|
609
650
|
size: { 13: 13 },
|
|
610
651
|
textTransform: 'uppercase',
|
|
611
|
-
color: colors.label.
|
|
652
|
+
color: colors.label.rotateHue(-40).saturate(1).darken(0.05),
|
|
612
653
|
},
|
|
613
654
|
'label-place-neighbourhood': {
|
|
614
655
|
minzoom: 14,
|
|
615
656
|
size: { 14: 12 },
|
|
616
657
|
textTransform: 'uppercase',
|
|
617
|
-
color: colors.label.
|
|
658
|
+
color: colors.label.rotateHue(-50).saturate(1).darken(0.05),
|
|
618
659
|
},
|
|
619
660
|
'label-motorway-shield': {
|
|
620
661
|
color: colors.shield,
|
package/dist/styles/eclipse.js
CHANGED
|
@@ -3,9 +3,6 @@ export default class Eclipse extends Colorful {
|
|
|
3
3
|
name = 'Eclipse';
|
|
4
4
|
constructor() {
|
|
5
5
|
super();
|
|
6
|
-
this.transformDefaultColors(color =>
|
|
7
|
-
color = color.hsl();
|
|
8
|
-
return color.lightness(100 - color.lightness()).rgb();
|
|
9
|
-
});
|
|
6
|
+
this.transformDefaultColors(color => color.invertLuminosity());
|
|
10
7
|
}
|
|
11
8
|
}
|
package/dist/styles/graybeard.js
CHANGED