-
-
Notifications
You must be signed in to change notification settings - Fork 777
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for multiple sprites in one style #1805
Conversation
Bundle size report: Size Change: +899 B
ℹ️ View DetailsNo major changes |
I like the sprite name in order to know from each sprite to take the icons from in order to avoid collision and the default key word. |
So we do need a key-value map of some sort.
I also do have doubts about this part.
Thought of this as of another PR. Or at least later in this PR...
As a specified in the OP, I couldn't find how to do this. As far as I understood, it's done in
So, first we need to support both strings (for the BC) and maps of some sort. Either an array of form |
look for See this PR for more references: |
What is the use case/scenario for having multiple sprites? |
For me - if I allow users to have custom map layers and in general more than one layer of map (not maplibre layer but a "map layer" where you can stack different styles one on top of the other) then having more than one sprite allows the site to be agnostic of style file and allow users to create their own styles and present them in the site. |
@HarelM Any idea of why do integration tests fail? Where should I look into? |
I'm not sure honestly, you'll need to try and run then locally and see what change caused them to fail... |
@HarelM |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work!! THANKS!!!
You can open it now. I'll merge this shortly. |
We'll need to make sure this is also documented well. |
Not sure what are you about. The Or are you talking about some other stuff? |
Yes, setStyle with diff is what I'm referring to as style update/patch. |
I've updated the initial commen for the PR. |
It might be the current implantation, but since now there's a meaning to diff in terms of adding new sprites or removing non used, it needs to be addressed. |
To clarify, the diffing refers to style diffing that happens on maplibre-gl-js/src/style-spec/diff.ts Line 319 in 66e1009
maplibre-gl-js/src/style/style.ts Line 1606 in 66e1009
or maplibre-gl-js/src/style/style.ts Line 1522 in 66e1009
in which case the behavior is as following:
|
@ambientlight for sprites I believe it's the same. |
@smellyshovel: I think the current behavior is correct, there maybe some confusion regarding what diffing stands for. Diffing refers to style diffing. Here is the example: <!DOCTYPE html>
<html lang="en">
<head>
<title>MapLibre GL JS debug page</title>
<meta charset='utf-8'>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel='stylesheet' href='../../dist/maplibre-gl.css' />
<style>
body { margin: 0; padding: 0; }
html, body, #map { height: 100%; }
</style>
</head>
<body>
<div id='map'></div>
<script src='../../dist/maplibre-gl-dev.js'></script>
<script>
const map = new maplibregl.Map({
container: 'map',
zoom: 12.5,
center: [-77.01866, 38.888],
style: 'https://demotiles.maplibre.org/style.json',
hash: true
});
map.showTileBoundaries = true;
map.on('load', () => {
window.setTimeout(() => {
// set glyphs and update symbol layers to new fonts
map.setGlyphs('https://atlas.microsoft.com/styling/glyphs/{fontstack}/{range}.pbf?api-version=2.0', {
validate: true
});
map.getStyle().layers
.forEach(layer => {
if (layer.type === 'symbol') {
map.setLayoutProperty(layer.id, 'text-font', ["StandardFont-Bold"]);
}
});
// move to a new style without glyphs and symbol layers
window.setTimeout(() => {
map.setStyle('https://demotiles.maplibre.org/style.json', {
transformStyle: (previousStyle, nextStyle) => {
const targetStyle = ({
...nextStyle,
layers: nextStyle.layers.filter(layer => layer.type !== 'symbol')
});
delete targetStyle.glyphs;
return targetStyle;
}
});
}, 10000);
}, 5000);
});
</script>
</body>
</html> In the above, if you map.setStyle to a style that has changed glyphs, previously, a full style reload would be performed, now the style would be updated (and thus diffed, as the set of operations would be computed in maplibre-gl-js/src/style-spec/diff.ts Line 319 in 66e1009
|
@HarelM: I've just verified the behavior to be as expected as per 66e1009, except only, on my side, I need to complete #1874 bug fix asap, since it may affect the sprite loading as discussed there. |
Thanks @ambientlight! |
for our case, where we have styles with ~1000 layers, the penalty of reloading the style from scratch is very high (x seconds) for just a sprite switch, which is a common case when switching between light and dark styles for example |
Changed API
None.
Main classes that were changed (inner impl.)
Map
,Style
.Updated API
map.setStyle
Now supports sprite value diffing. Namely, in case the sprites change with a call to
setStyle
, all the old sprites are removed and the new ones are added. So it's not exactly "diff"ing in its most accurate sense, but AFAIK changing sprite withsetStyle
previously was not possible at all.New API
style.json
's sprite propertyThis PR adds support for multiple sprite files per one style file while keeping the backwards compatibility intact.
Previously, a sprite could only be defined as a single URL to fetch both
.json
and.png
files from.Now, one can also pass a JSON-array with
{id: "id", url: "url"}
objects to have more than one sprite loaded per one style file (i.e. one sprite per one map).So both following declarations are now OK:
and
(As previously, the
sprite
declaration can still be skipped allogether).Resrtictions and validation.
All the
id
and all theurl
s must be unique. This is checked both initially on validating the style and using the new puclic API (see below), when validation is not explicitly disabled for them.Namespacing
Each sprite's
id
is used as a namespace for its images' names. So, if you sprite declaration looks like this:then all the images from both sprites should use
sprite1:
andsprite2:
prefixes when referenced. For example (for the above declaration):Images from the sprite with
id
"default" are not prefixed.That's done for the backwards-compatibility reasons. So that you don't have to majorly change your style file in case you want to start using the multi-sprites feature.
Public methods
map.getSprite()
Returns the currently used sprite always as an array. When no sprite is set for the map, it's
[]
.map.addSprite(id, url, options?)
Adds a sprite to the map style.
id
- The ID of the sprite to add. Must not conflict with existing sprites.url
- The URL to load the sprite fromoptions
- optionalStyleSetterOptions
object. The same as for the other similar PI methods (like{validate: false}
e.g.)Fires an error event if validation fails.
map.removeSprite(id)
Removes a sprite with the given ID from the map. Fires an error event in case there's no sprite with the specified ID exist.
id
- The ID of the sprite to addIf the sprite is declared as a single URL, you must use
"default"
as the ID.map.setSprite(spriteUrl, options?)
Sets the value of the style's sprite property.
spriteUrl
- Sprite URL to set.options
- optionalStyleSetterOptions
object. The same as for the other similar PI methods (like{validate: false}
e.g.)Only supports string-form declarations.
Glyphs
@ambientlight ???