-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Optionally persist layers and sources across styles #6180
Comments
This is a well-recognized problem, but there appear to be few designs that don't introduce significant additional complexity of their own. mapbox/DEPRECATED-mapbox-gl#25 has a proposal for one possible approach. |
For reference, here is a post that illustrates the kind of workaround that platform developers must do to manage runtime styling sources/layers on top of changing styles. |
@1ec5 , Would it be much work for the SDK to remove the source+layers from the mapview right before a style change, keep the references, and add them directly back when the style is ready? I think asking the developers to do this isn't efficient and it's not clear in the docs that this WILL happen on style changes. I would need to maintain a class level variable for |
I discovered a bug with the workaround in #7124 (comment). If you use a class level variable to hold a
I've resorted to wiping all the layers clean and starting fresh each time the style changes. Not perfect solution. Please consider this a friendly bump in priority for this feature. |
If I’m not mistaken, yanking a source out from under a layer that uses it could result in undefined behavior. So to be safe, you’d have to remove the layers before removing the source that they use, the change the style, then add the sources and layers back, in that order. I recognize that isn’t a far cry from starting afresh. |
Here's a broader tracking ticket for designing a style-spec level solution to this problem: mapbox/mapbox-gl-js#4225 |
mapbox/mapbox-gl-js#4225 would only be a complete solution inasmuch as we plan to remove the ability to switch styles altogether, although it would eliminate one use case for switching styles. |
@1ec5, you're right, I was removing source before layer. I've optimized my code but still getting errors var recordGeoJSON = MGLShapeSource(identifier: "record-source", shape: nil, options: nil)
...
...
func pseudoChangeMapStyle(){
if let recordS = self.mapView.style?.layer(withIdentifier: "record-style"){
self.mapView.style?.removeLayer(recordS)
}
self.mapView.style?.removeSource(self.recordGeoJSON)
//also tried:
/**
if let recordS = self.mapView.style?.source(withIdentifier: "record-source"){
self.mapView.style?.removeSource(recordS)
}
**/
...
self.mapView.styleURL = newStyle
}
func mapViewDidFinishLoading() {
....
style.addSource(self.recordGeoJSON)
let recordStyle = MGLLineStyleLayer(identifier: "record-style", source: self.recordGeoJSON)
...
style.addLayer(recordStyle)
....
}
func updateRecordingLine(_ geojson: JSON){
if let geojsonData = try? geojson.rawData() {
self.recordGeoJSON.shape = try? MGLShape(data: geojsonData, encoding: String.Encoding.utf8.rawValue)
}
//also tried
/**
if let geojsonData = try? geojson.rawData() {
if let source = self.mapView.style?.source(withIdentifier: "record-source") as? MGLShapeSource{
source.shape = try? MGLShape(data: geojsonData, encoding: String.Encoding.utf8.rawValue)
}
}
**/
}
func removeRecordingLine(){
if let source = self.mapView.style?.source(withIdentifier: "record-source") as? MGLShapeSource{
source.shape = nil
}
} I'll either get this error:
or this one:
or a crash in CF_RUN_LOOP. I think this is because my location delegate is trying to update As you can see above, I've tried Either way, what a mess. |
I've since removed class level style layers and sources variables and am reloading data on every style change in ☀️ |
Per nitaliano/react-native-mapbox-gl#812 (comment), React Native Mapbox GL automatically removes and readds layers and sources when the style URL changes, essentially working around this issue for the time being. Unfortunately, I think it foils any transitions between styles. |
Related: #12167 |
@1ec5 what are use cases for switching-style-but-persisting-some-sources/layers that couldn't (or shouldn't) be covered by composable style components? |
It’s difficult to answer concretely based on the current style component or nested style proposals, but a layer may be used to visualize data that remains relevant despite a wholesale change to the style. For example, it’s typical for an iOS application to display annotations on the map and expect the annotations to remain visible when switching between the Outdoors and Satellite styles. The iOS navigation SDK automatically switches between its day and night styles (for example, when entering or exiting a tunnel); the route line and any symbol layers representing destinations have to be reapplied manually. That’s workable for the navigation SDK, because the route line can be derived from the stored route data on demand. But an application that puts its own data on the map can’t use the map as a reliable storage mechanism if the style URL ever changes. I filed this issue as part of #6181, as a prerequisite for reimplementing the annotation API atop the runtime styling API. Developers treat MGLMapView as a data store when they add point and shape annotations to the map. They don’t expect the data to be manipulated (#6178, #7376) or lost as a result of ostensibly visual changes (this issue). |
Ah -- yeah, it may not be clear in the existing proposals in, but I think of this type of use case as one of the core requirements that any style components design should address. |
Perhaps “style components” is a misnomer in that case, because I think developers might still expect this behavior when switching between two wholly different styles, not necessarily a single style that composes or nests two substyles. For example, consider this workflow in MapKit or the Google Maps SDK:
This workflow doesn’t require the developer to create or customize a style to accommodate the pins or the switch from Standard to Satellite. It just works. This workflow is currently implemented with the annotation API. If the style components feature is to address this workflow, then I think it would subsume the concept of a style, bringing us back to square one. |
This issue has been automatically detected as stale because it has not had recent activity and will be archived. Thank you for your contributions. |
Still needed as a prerequisite for #6181. |
@1ec5 In mapbox-ios: I wonder if modifying styleURL to preserve layers and sources is supported? |
No, there is no general solution to the problem at the moment. Your options are:
/cc @chloekraw |
This issue has been automatically detected as stale because it has not had recent activity and will be archived. Thank you for your contributions. |
Annotations added to the map persist even after switching styles. This can be especially handy for an application that allows the user to switch back and forth between Streets and Satellite: any dropped pins, drawn shapes, or route lines remain on the map the whole time. The developer isn’t responsible for rebuilding the data on each style change.
Per #5626 (comment), for the runtime styling API to have parity with the annotation API, there would need to be some way for certain layers and sources to optionally persist after switching styles. I’m not sure whether the SDK would have to take full responsibility for persisting this data, or whether mbgl can keep track of some state.
/cc @jfirebaugh @incanus @frederoni
The text was updated successfully, but these errors were encountered: