Reputation: 200
I use mapbox to display a geojson on an iOS and Android app.
The same geojson is display differently on both platform. I think some shapes hide others on iOS.
There is no MGLGeoJSONSource on mapbox ios sdk, it's look like they remove it. So it's longer a lot to achieve the same result.
Maybe someone has a better way to dot it?
Here is my java code:
JSONArray features = json.getJSONArray("features");
for (int i = 0; i < features.length(); i++) {
JSONObject feature = features.getJSONObject(i);
GeoJsonSource geoJsonSource = new GeoJsonSource(i, feature.toString());
JSONObject properties = feature.getJSONObject("properties");
int rounded_value = (int)Math.round(properties.getDouble("value"););
list_value_geojson.add(new AbstractMap.SimpleEntry<>(rounded_value, geoJsonSource));
}
for (int i=0; i < list_value_geojson.size(); i++){
Map.Entry<Integer, GeoJsonSource> entry = list_value_geojson.get(i);
mapboxMap.addSource(entry.getValue());
FillLayer fillLayer = new FillLayer(entry.getValue().getId(), entry.getValue().getId());
fillLayer.setProperties(PropertyFactory.fillColor(Color.parseColor(hashMapColors.get(entry.getKey()))));
mapboxMap.addLayer(fillLayer);
}
And here is my Swift code:
if let features = jsonDict["features"] as? NSArray {
var sourceIndex = 0
for feature in features {
if let feature = feature as? NSDictionary {
if let geometry = feature["geometry"] as? NSDictionary {
let coordinates_array_of_array = geometry["coordinates"] as! NSArray
for coordinates_array in coordinates_array_of_array{
var coordinates_collection : [CLLocationCoordinate2D] = []
let locations = coordinates_array as? [[Double]]
for location in locations! {
// Make a CLLocationCoordinate2D with the lat, lng
let coordinate = CLLocationCoordinate2D(latitude: location[1], longitude: location[0])
// Add coordinate to coordinates array
coordinates_collection.append(coordinate)
}
if let properties = feature["properties"] as? NSDictionary {
let mglpf = MGLPolygonFeature(coordinates: coordinates_collection, count: UInt(coordinates_collection.count))
mglpf.title = String(properties["value"] as! Int32)
mglpf.attributes = ["color":getColorFromValue(value: mglpf.title!)]
let source = MGLShapeSource(identifier: "shapeSource"+String(sourceIndex), features: [mglpf], options: nil)
mapbox?.style?.addSource(source)
sourceIndex = sourceIndex + 1
let layer = MGLFillStyleLayer(identifier: "layer"+String(sourceIndex), source: source)
layer.fillColor = MGLStyleValue<UIColor>(rawValue: Util.hexStringToUIColor(hex: getColorFromValue(value: mglpf.title!)))
mapbox?.style?.addLayer(layer)
}
}
}
}
}
}
Upvotes: 1
Views: 2313
Reputation: 200
Here is how I finally made it: First I parse JSON in order to get every color and the associate value, then I create a FillStyleLayer for every color and set predicate attribute to restrict the color to a specific value.
let url = URL(fileURLWithPath: jsonPath)
do {
// Load and serialize the GeoJSON into a dictionary filled with properly-typed objects
if let jsonDict = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String : AnyObject] {
// parse json to Get all colors with their value and put it in the dictionnary
if let features = jsonDict["features"] as? NSArray {
for feature in features {
if let feature = feature as? NSDictionary {
if let properties = feature["properties"] as? NSDictionary {
let color = properties["color"] as! String
let value = properties["value"] as! Double
if colorByValueArray.index(forKey: value) == nil {
colorByValueArray[value] = color
}
}
}
}
}
//Add GeoJSON to map source
let mglss = MGLShapeSource(identifier: DrawGeoJSON.TAG_SOURCE_PREFIX + shape_type, url: NSURL(fileURLWithPath: jsonPath) as URL, options: nil)
mapbox.style?.addSource(mglss)
//Create color rules with filllayer
//This will create a fillLayer for each different value/color
//Some values from geoJSON are not int value. == operator doesn't work with this float value so I had to use < > operators
for colorDic in colorByValueArray {
let mglfsl = MGLFillStyleLayer(identifier: DrawGeoJSON.TAG_LAYER_PREFIX + shape_type + String(colorDic.key), source: mglss)
mglfsl.sourceLayerIdentifier = DrawGeoJSON.TAG_SOURCE_PREFIX + shape_type
mglfsl.predicate = NSPredicate(format: "value < %d AND value >= %d", Int(colorDic.key)+1, Int(colorDic.key))
mglfsl.fillColor = MGLStyleValue<UIColor>(rawValue: Util.hexStringToUIColor(hex: colorDic.value))
mapbox.style?.addLayer(mglfsl)
}
}
}
catch
{
print("GeoJSON parsing failed")
}
Upvotes: 1
Reputation: 976
One option is to use a MGLShapeSource to work with GeoJSON data. You can then use that as your source for the MGLFillStyleLayer.
You may also want to look into using the data driven styling that is being introduced in the latest betas of the Android and iOS SDKs. For iOS, you can use a MGLSourceStyleFunction
with the fillColor
on your MGLFillStyleLayer
to style it based on feature attributes.
Upvotes: 2