mapbox / mapbox-gl-native

Interactive, thoroughly customizable maps in native Android, iOS, macOS, Node.js, and Qt applications, powered by vector tiles and OpenGL
https://mapbox.com/mobile
Other
4.38k stars 1.32k forks source link

Style-compliant JSON in Android and iOS SDKs #13467

Open kalimar opened 6 years ago

kalimar commented 6 years ago

We have a customer currently building a hybrid app with Mapbox. The app is set up such that most of the business logic lives in javascript, and then actual rendering commands are handed off to native code when running in iOS/Android. They were able to get through the initial mapbox-gl-js implementation pretty quickly and now are working on duplicating that functionality with the iOS native SDK. They are passing the same source/layer objects to native code that they are using for the JS implementation. An example of this would be:

const map = isNativeDevice ? window.nativePlugin : this.map;
map.addSource('drone', {
  "type": "geojson",
  "data": {
    "type": "Point",
    "coordinates": [-123.11387638888888, 38.42628472222222],
  },
});

map.addLayer({
  "id": "drone-symbol",
  "type": "symbol",
  "source": "drone",
  "layout": {
    "icon-image": "drone",
    "icon-size": 0.5,
  },
});

This has ended up being a bit clunkier than they were hoping, as they need to parse the objects coming from JS, instantiate the correct native object, and then update appropriate properties on those objects. Is there any way to work directly with style-compliant JSON in the native SDKs. For example, the Objective C handling for addLayer in the above case might look something like:

(void) addLayer:(CDVInvokedUrlCommand*)command {
    // layerData comes from JS context
    NSDictionary *layerData = [command.arguments objectAtIndex:0];
        NSData *jsonData = [NSJSONSerialization dataWithJSONObject:layerData
        options:0
        error:NULL];
    MGLStyleLayer *newLayer = [MGLStyleLayer layerWithData:jsonData];
    [self.mapView addLayer:newLayer];
}

They were hoping there was an existing mechanism for parsing JSON objects directly into native style layers and sources. Given that you can do this for a complete map style file, it seemed likely that functionality would exist somewhere in the native SDK (but is perhaps not exposed). Exposing that functionality would drastically reduce the amount of code needed to maintain consistency between android/ios/web.

ekigamba commented 5 years ago

I also think the Mapbox SDK style parsing, layer parsing and source parsing should be exposed to provide more functionality to developers. I also have the layer definitions and source definitions but cannot add them as json to the style. I have to write code to parse it and read into the Layer and Source child classes provided.

I am also experiencing issues converting some paint and layout properties which in v10 of streets style were expressed as functions using base and stops but I can't find the function for that or how to pass that to the PropertyValue classes.

I don't want to add additional code in my project to parse the json layers & sources for a couple of reasons:

@tobrun, @zugaldia, anyone, Could you help me out?
I am trying to create a base layer switcher for Android where a base layer is going to be a group of layers & sources. The original style without a base layer or with a default base layer is designed and created on Mapbox or in a style. That style contains the layers and the properties on which data is added and modified at runtime. The ability to switch between a satellite base layer and streets base layer depending on the structures/information by each base layer.

zugaldia commented 5 years ago

/cc: @tmpsantos as this looks like something we'd like to add to core first, instead of implementing it twice (with the subsequent roundtrips) on the platform side.

zugaldia commented 5 years ago

/cc: @chloekraw per chat.

tmpsantos commented 5 years ago

I actually suggested something like this before: https://github.com/mapbox/mapbox-gl-native/issues/5623

1ec5 commented 4 years ago

They were hoping there was an existing mechanism for parsing JSON objects directly into native style layers and sources. Given that you can do this for a complete map style file, it seemed likely that functionality would exist somewhere in the native SDK (but is perhaps not exposed).

On iOS and macOS, you can use +[NSJSONSerialization dataWithJSONObject:] in conjunction with +[MGLShape shapeWithData:encoding:error:] to more easily create an MGLShapeSource from part of the GeoJSON source JSON – the GeoJSON part. #6386 tracks a way to create a whole MGLStyle from JSON, which could easily lead to a way to create just an MGLSource or MGLStyleLayer from JSON. #16231 gets part of the way there by making it possible to serialize a layer to JSON in mbgl, but it needs to be hooked up at the SDK level too.