Skip to content

Commit c52b5c3

Browse files
stepankuzminibesora
authored andcommitted
Landmark Icons follow-up (internal-2307)
1 parent 0b03660 commit c52b5c3

File tree

6 files changed

+229
-161
lines changed

6 files changed

+229
-161
lines changed

debug/landmark-icons.html

Lines changed: 139 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -28,115 +28,169 @@
2828
<script type="module">
2929
const style = await fetch('https://api.mapbox.com/styles/v1/mapbox/standard?access_token=' + mapboxgl.accessToken).then(res => res.json());
3030

31-
style['sources']['landmarks-poi'] = {
32-
type: 'vector',
33-
url: 'mapbox://mapbox-geodata.landmarks-poi-icons-02-25'
34-
};
35-
36-
style['sources']['landmark-icons'] = {
37-
type: 'raster-array',
38-
tiles: ['https://api.mapbox.com/rasterarrays/v1/mapbox.mapbox-landmark-icons-v1/{z}/{x}/{y}.mrt?jobid=2025-02-24'],
39-
minzoom: 10,
40-
maxzoom: 10,
41-
bounds: [-12.14, 49.77, 3.956, 58.89],
42-
raster_layers: [{id: 'landmark-icons'}]
43-
};
44-
45-
style['iconsets'] = {
31+
style.iconsets = {
4632
landmarks: {
4733
type: 'source',
48-
source: 'landmark-icons'
34+
source: 'mapbox-landmarks'
4935
}
5036
};
5137

52-
style.layers = style.layers.concat([
38+
style.sources = {
39+
...style.sources,
40+
'landmarks-poi': {
41+
type: 'vector',
42+
url: 'mapbox://mapbox-geodata.landmarks-poi-staging',
43+
},
44+
'mapbox-landmarks': {
45+
type: 'raster-array',
46+
url: 'mapbox://mapbox.mbx-landmark-icons-v1-staging',
47+
}
48+
};
49+
50+
style.layers = [
51+
...style.layers,
5352
{
54-
"id": "landmark-poi-marker-maki-poi-short",
53+
"id": "landmark-icon",
5554
"type": "symbol",
5655
"source": "landmarks-poi",
5756
"source-layer": "landmarks-poi",
58-
"minzoom": 8,
59-
"maxzoom": 10,
60-
"paint": {
61-
"text-halo-color": "hsla(0, 91%, 69%, 0.4)",
62-
"text-halo-width": 1,
63-
"text-color": "hsl(0, 0%, 0%)",
64-
"text-opacity": [
57+
"minzoom": 10,
58+
"maxzoom": 17,
59+
"filter": [
60+
"all",
61+
["has", "local_rank"],
62+
["<=", ["get", "local_rank"], 1],
63+
[
6564
"step",
66-
["get", "local_rank"],
65+
["zoom"],
66+
["==", ["geometry-type"], "Point"],
67+
10,
68+
[">=", ["get", "local_rank"], 0.9],
69+
11,
70+
[">=", ["get", "local_rank"], 0.8],
71+
12,
72+
[">=", ["get", "local_rank"], 0.7],
73+
13,
74+
[">=", ["get", "local_rank"], 0.5],
75+
13.5,
76+
[">=", ["get", "local_rank"], 0.3],
77+
14,
78+
[">=", ["get", "local_rank"], 0.1]
79+
],
80+
[
81+
"case",
82+
["<=", ["pitch"], 45],
83+
true,
84+
["all", ["<=", ["distance-from-center"], 2], [">", ["pitch"], 45]],
85+
true,
86+
false
87+
]
88+
],
89+
"paint": {
90+
"symbol-z-offset": [
91+
"interpolate",
92+
["linear"],
93+
["zoom"],
94+
14,
95+
0,
96+
15,
97+
[
98+
"case",
99+
["config", "show3dObjects"],
100+
["+", ["to-number", ["get", "mapbox:debug:model_height"]], 20],
101+
0
102+
]
103+
],
104+
"icon-image-cross-fade": [
105+
"interpolate",
106+
["linear"],
107+
["measure-light", "brightness"],
108+
0.25,
67109
0,
68-
0.1,
69110
0.3,
70-
0.5,
71-
0.75,
72-
0.75,
73111
1
74-
]
75-
},
76-
"layout": {
77-
"visibility": "visible",
78-
"text-field": ["to-string", ["get", "short_name_en"]],
79-
"symbol-z-elevate": true,
80-
"text-font": [
81-
"Poppins Medium",
82-
"DIN Pro Medium",
83-
"Open Sans Semibold",
84-
"Arial Unicode MS Bold"
85112
],
86-
"icon-image": ["image", ["concat", "landmark-icons", "/", ["get", "icon_name"]], {"iconset": {"id": "landmarks"}}],
87-
"icon-color": "hsl(0, 100%, 50%)",
88-
"icon-size": 0.5,
89-
"symbol-placement": "point",
90-
"text-size": 13,
91-
"text-anchor": "top",
92-
"text-offset": [0, 2],
93-
"symbol-sort-key": ["-", 1, ["get", "prominence"]]
94-
}
95-
},
96-
{
97-
"id": "landmark-poi-marker-maki-poi-full",
98-
"type": "symbol",
99-
"source": "landmarks-poi",
100-
"source-layer": "landmarks-poi",
101-
"minzoom": 10,
102-
"paint": {
103-
"text-halo-color": "hsla(0, 91%, 69%, 0.4)",
104-
"text-halo-width": 1,
105-
"text-color": "hsl(0, 0%, 0%)",
106-
"text-opacity": [
107-
"step",
108-
["get", "local_rank"],
109-
0.3,
110-
0.3,
111-
0.5,
112-
0.75,
113-
0.75,
114-
0.9,
113+
"icon-opacity": ["interpolate", ["linear"], ["zoom"], 15.7, 1, 16, 0],
114+
"icon-emissive-strength": [
115+
"match",
116+
["config", "theme"],
117+
"monochrome",
118+
[
119+
"interpolate",
120+
["linear"],
121+
["measure-light", "brightness"],
122+
0.25,
123+
0.5,
124+
0.3,
125+
1
126+
],
115127
1
116-
]
128+
],
129+
"text-color": [
130+
"match",
131+
["config", "theme"],
132+
"monochrome",
133+
[
134+
"interpolate",
135+
["linear"],
136+
["measure-light", "brightness"],
137+
0.25,
138+
"hsl(0, 0%, 40%)",
139+
0.3,
140+
"hsl(0, 0%, 35%)"
141+
],
142+
[
143+
"interpolate",
144+
["linear"],
145+
["measure-light", "brightness"],
146+
0.28,
147+
"hsl(240, 15%, 75%)",
148+
0.3,
149+
"hsl(0, 0%, 35%)"
150+
]
151+
],
152+
"text-halo-color": [
153+
"interpolate",
154+
["linear"],
155+
["measure-light", "brightness"],
156+
0.25,
157+
"hsla(0, 0%, 0%, 1)",
158+
0.3,
159+
"hsla(0, 0%, 100%, 1)"
160+
],
161+
"text-halo-width": 1,
162+
"text-opacity": ["interpolate", ["linear"], ["zoom"], 15.7, 1, 16, 0]
117163
},
118164
"layout": {
119-
"visibility": "visible",
120165
"text-field": ["to-string", ["get", "short_name_en"]],
121-
"symbol-z-elevate": true,
166+
"icon-allow-overlap": false,
167+
"icon-padding": 0,
122168
"symbol-sort-key": ["-", 1, ["get", "local_rank"]],
123-
"text-font": [
124-
"Poppins Medium",
125-
"DIN Pro Medium",
126-
"Open Sans Semibold",
127-
"Arial Unicode MS Bold"
169+
"text-font": ["DIN Pro Medium"],
170+
"icon-image": [
171+
"image",
172+
["concat", "landmark-icons", "/", ["get", "icon_name"], "-dark"],
173+
{
174+
"iconset": {
175+
"id": "landmarks"
176+
}
177+
},
178+
["concat", "landmark-icons", "/", ["get", "icon_name"]],
179+
{
180+
"iconset": {
181+
"id": "landmarks"
182+
}
183+
}
128184
],
129-
"icon-image": ["image", ["concat", "landmark-icons", "/", ["get", "icon_name"]], {"iconset": {"id": "landmarks"}}],
130-
"icon-size": 0.5,
185+
"icon-size": ["interpolate", ["linear"], ["zoom"], 13.8, 0.8, 14, 1],
131186
"symbol-placement": "point",
132-
"text-size": 13,
187+
"text-size": ["interpolate", ["linear"], ["zoom"], 13.8, 12, 14, 14],
188+
"text-padding": 10,
133189
"text-anchor": "top",
134190
"text-offset": [0, 2]
135191
}
136-
}
137-
]);
138-
139-
console.log(style);
192+
},
193+
];
140194

141195
const map = window.map = new mapboxgl.Map({
142196
container: 'map',

src/data/bucket/symbol_bucket.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -690,14 +690,19 @@ class SymbolBucket implements Bucket {
690690
const unevaluatedLayoutValues = layer._unevaluatedLayout._values;
691691
const {iconPrimary, iconSecondary} = getScaledImageVariant(icon, this.iconSizeData, unevaluatedLayoutValues['icon-size'], canonical, this.zoom, symbolFeature, this.pixelRatio, iconScaleFactor);
692692
const iconPrimaryId = iconPrimary.id.toString();
693-
const primaryIcons = icons.get(iconPrimaryId) || [];
694-
primaryIcons.push(iconPrimary);
695-
icons.set(iconPrimaryId, primaryIcons);
693+
if (icons.has(iconPrimaryId)) {
694+
icons.get(iconPrimaryId).push(iconPrimary);
695+
} else {
696+
icons.set(iconPrimaryId, [iconPrimary]);
697+
}
698+
696699
if (iconSecondary) {
697700
const iconSecondaryId = iconSecondary.id.toString();
698-
const secondaryIcons = icons.get(iconSecondaryId) || [];
699-
secondaryIcons.push(iconSecondary);
700-
icons.set(iconSecondaryId, secondaryIcons);
701+
if (icons.has(iconSecondaryId)) {
702+
icons.get(iconSecondaryId).push(iconSecondary);
703+
} else {
704+
icons.set(iconSecondaryId, [iconSecondary]);
705+
}
701706
}
702707
}
703708

src/render/image_manager.ts

Lines changed: 31 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -357,40 +357,41 @@ class ImageManager extends Evented {
357357
}
358358

359359
const images = id.iconsetId ? this._iconsets[scope][id.iconsetId] : this._images[scope];
360-
if (!images[id.name]) {
361-
// eslint-disable-next-line
362-
// TODO: `styleimagemissing` event should also include `iconsetId`
363-
this.fire(new Event('styleimagemissing', {id: id.name}));
364-
}
365360
const image = images[id.name];
366-
if (image) {
367-
// Clone the image so that our own copy of its ArrayBuffer doesn't get transferred.
368-
const styleImage = {
369-
// Vector images will be rasterized on the worker thread
370-
data: image.usvg ? null : image.data.clone(),
371-
pixelRatio: image.pixelRatio,
372-
sdf: image.sdf,
373-
usvg: image.usvg,
374-
version: image.version,
375-
stretchX: image.stretchX,
376-
stretchY: image.stretchY,
377-
content: image.content,
378-
hasRenderCallback: Boolean(image.userImage && image.userImage.render)
379-
};
380-
381-
if (image.usvg) {
382-
// Since vector images don't have any data, we add the width and height from the source svg
383-
// so that we can compute the scale factor later if needed
384-
Object.assign(styleImage, {
385-
width: image.icon.usvg_tree.width,
386-
height: image.icon.usvg_tree.height
387-
});
388-
}
389361

390-
response.set(ImageId.toString(id), styleImage);
391-
} else {
362+
if (!image) {
363+
// Don't fire the `styleimagemissing` event if the image is a part of an iconset
364+
if (id.iconsetId) continue;
365+
392366
warnOnce(`Image "${id.name}" could not be loaded. Please make sure you have added the image with map.addImage() or a "sprite" property in your style. You can provide missing images by listening for the "styleimagemissing" map event.`);
367+
this.fire(new Event('styleimagemissing', {id: id.name}));
368+
continue;
393369
}
370+
371+
// Clone the image so that our own copy of its ArrayBuffer doesn't get transferred.
372+
const styleImage = {
373+
// Vector images will be rasterized on the worker thread
374+
data: image.usvg ? null : image.data.clone(),
375+
pixelRatio: image.pixelRatio,
376+
sdf: image.sdf,
377+
usvg: image.usvg,
378+
version: image.version,
379+
stretchX: image.stretchX,
380+
stretchY: image.stretchY,
381+
content: image.content,
382+
hasRenderCallback: Boolean(image.userImage && image.userImage.render)
383+
};
384+
385+
if (image.usvg) {
386+
// Since vector images don't have any data, we add the width and height from the source svg
387+
// so that we can compute the scale factor later if needed
388+
Object.assign(styleImage, {
389+
width: image.icon.usvg_tree.width,
390+
height: image.icon.usvg_tree.height
391+
});
392+
}
393+
394+
response.set(ImageId.toString(id), styleImage);
394395
}
395396

396397
callback(null, response);

0 commit comments

Comments
 (0)