Mapbox-gl-native: Port feature state APIs to Native

Created on 17 Jul 2018  Â·  16Comments  Â·  Source: mapbox/mapbox-gl-native

Port of https://github.com/mapbox/mapbox-gl-js/pull/6263.

GL-Native's separation of Style/Render-Style classes requires that the feature state APIs sync changes to the state across threads on platforms that implement async rendering. The port will be more complicated than the SourceCache based implementation in gl-js.

Native SDKs will need to expose feature state APIs on top of the core implementation, and support the feature-state expressions.

cc @tobrun @1ec5 @mollymerp @ansis

Android GL JS parity gl-ios iOS macOS

Most helpful comment

Any progress or planning/estimate for this feature? I hope this can be ported to iOS / Android as it is a really nice way to style selection states on top of external data.

All 16 comments

Native SDKs will need to expose feature state APIs on top of the core implementation, and support the feature-state expressions.

For the iOS/macOS API, ideally the getter and setter would be added to MGLVectorTileSource, MGLShapeSource, and MGLComputedShapeSource. That would reduce the number of parameters needed for the setter.

Can the setter accept an MGLFeature returned from a feature querying method? Those features currently lack context such as the containing style layer or source layer: #7162. The GL JS implementation also accepts a “feature identifier” object containing a source, sourceLayer, and id, which would imply a method like -[MGLVectorTileSource setState:forFeatureWithIdentifier:sourceLayerIdentifier:].

The setter can accept a whole dictionary as state, which is quite unlike most state properties in Cocoa libraries that are typed as enumerations. The closest Cocoa analogy to the concept of “feature state” that I can think of would be the context parameter of -[NSExpression expressionValueWithObject:context:], which is associated with the variable syntax in NSExpression format strings. However, we’ve already repurposed that variable syntax for expression variables and for certain special expressions like $featureIdentifier.

/cc @fabian-guerra

@1ec5 I opened #11846 previously to add more context to features returned from the querying methods. If that context can be added to MGLFeature in some way, then that can be the input for the setState: method.

@jfirebaugh any eta on this?

Looking forward to this one as well!

Hey Mapbox folks – Is there an updated ETA on this?

Hey Mapbox folks – Is there an updated ETA on this?

Hi @johnnyux, we are working on reducing the gap between GL Native and GL JS (https://github.com/mapbox/mapbox-gl-native/blob/master/platform/node/test/ignores.json) but this is not the highest priority ATM because normally the use case has to do with hover a cursor over the feature which is not so common on mobile.

Hi @tmpsantos.

We use this feature extensively for controlling the display and stylising of elements as the application state changes, not just for hover interactions, which is just an introduction use case to the feature. The feature is more powerful to be able to change the style of map elements, layers, etc without requiring you to change the geojson data feature properties - which turns out to be an expensive call or by dynamically modifying the layer filters - also not ideal. We use it extensively for styling layers, paths, features etc individually which allows us to have much better interaction states with the map. Limiting the use case discussion to a hover state is not really supporting all of the interactive states that is offered by this feature in the mapbox-gl-js implementation. It is mandatory for creating effective interactive maps with more complex state than just marker hovers on a map.

I realise that it is a harder implementation, but this lack of parity does mean the techniques to target features and set their state to be incredibly expensive and means we need to create multiple types of styles to deal with web/web-mobile and can't implement the same styles and state models in native.

Happy to talk more about use cases.

Cheers
Cam

Hi @tmpsantos.

Just wanted to add on @cammanderson comment.

This feature would be extremely valuable to us. Right now we have to add many different layers / styles to control the display and style of our application elements. We'd use this feature extensively.

Not sure how you prioritize features internally and this seems like it would require some non trivial work, but this is definitely more than a nice to have hover feature.

Adding a screenshot of feature state demo on mbgl-glfw app. The demo implements the same hover effect as this GL-JS example.

Screenshot from 2019-09-04 15-33-19

Assigning @tarigo for the android bindings

The core part has now been merged (PR #15480).

Any progress or planning/estimate for this feature? I hope this can be ported to iOS / Android as it is a really nice way to style selection states on top of external data.

It's been two years since this request was filed. Can we get an update?

Hi, another seven months passed, would you be able to give us some insight into your roadmap for this, please? This feature would make things so much easier on mobile!

This feature is available on the v10.0.0 of the mobile SDKs:

Public API for Android implementation of MapboxMap#setFeatureState:

  /**
   * Update the state map of a feature within a style source.
   *
   * Update entries in the state map of a given feature within a style source. Only entries listed in the
   * \p state map will be updated. An entry in the feature state map that is not listed in \p state will
   * retain its previous value.
   *
   * Note that updates to feature state are asynchronous, so changes made by this method migth not be
   * immediately visible using getStateFeature().
   *
   * @param sourceId Style source identifier.
   * @param sourceLayerId Style source layer identifier (for multi-layer sources such as vector sources).
   * @param featureId Identifier of the feature whose state should be updated.
   * @param state Map of entries to update with their respective new values.
   */
  fun setFeatureState(
    sourceId: String,
    sourceLayerId: String?,
    featureId: String,
    state: Value
  )

on iOS it's availlable as mapView.__map.setFeatureState(..)

Was this page helpful?
0 / 5 - 0 ratings