-
-
Notifications
You must be signed in to change notification settings - Fork 83
Design Proposal: Global map state #886
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
Comments
This is a really interesting idea and I'd like to weigh in from the implementation side. Having overseen the MapLibre Native upgrade this year and last, I can say that the flexibility in the style spec causes a lot of extra work at the implementation level. The difference in perspective between the style sheets and the GPU focused real time rendering is vast. That gulf has to be bridged by the renderer implementations each time they see a style sheet and a vector tile. The MapLibre toolkits already do this work, so that's good for MapLibre. It bad for anyone else who might want to write a new renderer and it does use a lot of extra power on mobile devices for flexibility that's rarely used. At the root, the problem is that style sheets are meant to be flexible enough for editing and be simple enough to be parsed by the map renderer. Those two goals pull in opposite directions. Rather than adding more flexibility into the style spec itself, I wonder if it might be time to break things apart. Add more flexibility in a high level version of the style sheet and remove flexibility from the low level. In your example, perhaps add meta-tags to the style sheet that denote states and then process that into multiple actual style sheets. To make switching easier, name things the same, provide unique IDs, perhaps. That sort of thing. Maybe follow the logic all the way into generating style sheets the same way we do static HTML sites these days. It would be kind of nice to just dump a block of Javascript in the middle of a style sheet to do some logic at generation time. On the compiled side, you could imagine a header block to tell us what's in the style sheet. There's all sorts of stuff we could turn off if we didn't have to expect it and new renderers could have some idea of what they need to support to get most of the way there. A bit more than you're looking for, I'm sure, so the short version is... maybe go in this other direction? |
Thanks for the comment, interesting perspective. We could also describe this same design proposal as a set of style input parameters, which are used to generate a concrete style. I don't have a concrete proposal of how this would look like from the API and implementation perspective. I do agree that it seems valuable to move as much processing away from parsing the style and low level dynamic style elements, into a simple style specification that can be fed to a GPU for rendering. |
Worth noting that I found this discussion whilst looking for a means by which I could dynamically alter the "text-size" & "line-width" properties (be they constant or expression) due to high vs low DPI screens in the Win32 world. At the moment, I'm having to pre-process the style JSON and replace wildcards with the calculated DPI at style load time (requiring a style reload when the window is moved between monitors). Not great, but OK for styles I code personally, however not a reasonable option for client created styles. Being able to access global variable representing the DPI scale factor for this in expressions would make creating these styles far more manageable. |
At TomTom, we see great potential in having this feature for map personalization purposes. Some of the use cases it enables for navigation applications are:
To address other options:
Extending style spec seems the most straightforward and viable solution for fast adoption of this feature. All filtering logic is still in in one place, changing it does not require code modification which reduces implementation and maintenance cost, and cycle time to deliver new features. |
Excited to see this become reality - this can greatly simplify code bases needing to vary styling. My use case is I have "sets" of fieldwork symbols, and I'd like to emphasis the currently selected set whilst fading all other points. With a global state I could simply pass the selected fieldwork id! |
To facilitate the discussion I created implementation (style-spec, maplibre-gl-js) and sandbox, so that everyone can play with the proposed functionality: For the sake of the PoC I keep things simple - the expression is not compound (you cannot use another expression as a value) and setting global state always reloads sources because expression may be used inside |
I have some concerns regarding the style validation and integration.
To address this, we could specify the defaults and types in a new style property. Let's refer to this property as
Having such property in place:
What do you think of this approach? |
How is it different than missing values in a property of a feature ( |
That's a good example. Building further on the integration problem. Let's say I am developing a navigation SDK that relies on the |
I'm not sure I understand the last part, but I'm not against default values, I'm just saying that it might be easier if they were optional. |
The ability to set style-wide state and refer to it in individual expressions would be extremely useful. Lots of client code is forced to iterate over all the layers in the style and apply the same transformation to the filter or paint or layout properties. Examples include mapbox-gl-language, maplibre-gl-dates (which I maintain), OpenStreetMap Americana, and code built right into MapLibre Native for iOS. To guard against repeated applications of the same transformation, most of these plugins have code that wraps each expression in a I don’t know if the current implementation of this proposal would be more performant, but it would certainly be more manageable than the current approach. For performance testing, this OpenHistoricalMap animation demonstrates the iterative approach in a fairly hot loop. |
For people following this thread, the discussion continues in: #1044 |
Seeing #1044 is merged, I think this issue can be closed. |
Design Proposal: Global map state
Motivation
Split off from #516 (comment), and originally posted / requested in maplibre/maplibre-gl-js#4964.
The goal is to store some global map state on the
Map
object, which can be used in the style. This makes it easier to let the user configure the map for certain preferences, which can then dynamically be used in the style to modify the appearance of the map.My concrete use case is supporting a map theme, where the user selects a theme and this impacts the look and feel of the web application, in particular the features on the map.
Proposed Change
Introduce a function
map-state
which takes a single string argument which is the key.The return value is the value in the global map state, if present, otherwise
null
.Examples:
Handling unset key in the map state
The map state will function as a key-value dictionary, so the values in the map state contains string keys and string, numeric or boolean values. We could choose to support e.g. arrays as values as well.
The
map-state
function should have the same semantics asfeature-state
which uses data set on a feature.API Modifications
The expression
map-state
will be supported.Migration Plan and Compatibility
No migration needed, this is new functionality.
The feature should not be complex to implement in the specification and client libraries because:
feature-state
already exists, and this function is similar although it takes the state from a different placeProbably the biggest complexity is managing the global map state changing its value, and recomputing the style for the impacted features on the map.
Rejected Alternatives
let
expressions and dynamically transforming the style. This still couples the client with the map style, and still requires walking the expressions in the map style to dynamically replace thelet
values with the configured values.The text was updated successfully, but these errors were encountered: