Reputation: 77
I need to find a way to convert markers from MGLPointAnnotation
to MGLShapeSource
or similar, in order to add the markers to a map layer and have full control over how to display and cluster them on the map, for example.
I am building an iOS App using MapBox SDK v5.2
.
The App generates markers internally (title, subtitle, coordinates and icon image name) and the markers are displayed on the map with a callout when tapped. The markers are created using MGLPointAnnotation()
and added to the map using mapView.addAnnotation()
.
But in order to have full control on how the markers are displayed, for example clustering them based on zoom level or toggling them ON/OFF, I need to add the markers to a Map layer, using, for example, MGLShapeSource
and then style.addSource()
and style.addLayer()
.
The problem is I cannot find a way to the converter from MGLPointAnnotation
to MGLShapeSource
or similar.
I have investigated this but the only solution I can think of is to have the marker information contained in a GeoJSON
file. But I want to avoid that as the markers are generated within the App when its running, and not from an external read-only GeoJSON file.
Example on how one single poi is created:
let poi1 = MGLPointAnnotation()
poi1.coordinate = CLLocationCoordinate2D(latitude: 38.788534, longitude: -9.494489)
poi1.title = "poi1"
poi1.subtitle = "This is the text for poi1"
poiTitleImage[poi1.title!] = "icon1"
mapView.addAnnotation(poi1)
Upvotes: 2
Views: 1407
Reputation: 976
You can create an MGLShapeSource
with an array of MGLPointAnnotation
or MGLPointFeature
objects. From there, you can add a clustered layer similar to this clustering example.
If you would also like to assign text or other data for each point, use MGLPointFeature
objects, then assign the text as an attributes value.
For example:
var features = [MGLPointFeature]()
for _ in 1...100 {
let point = MGLPointFeature()
let lat = Double(arc4random_uniform(180) / 2)
let lon = Double(arc4random_uniform(360) / 2)
point.coordinate = CLLocationCoordinate2D(latitude: lat, longitude: lon)
point.attributes["title"] = "\(lat) \(lon)"
features.append(point)
}
let source = MGLShapeSource(identifier: "clusteredFeatures",
features: features,
options: [.clustered: true, .clusterRadius: 20])
style.addSource(source)
An example of how to present a callout containing the information can be found on the Mapbox website. It seems like the handleMapTap
method may contain what you're looking for.
Essentially, you'll query the map where the user taps. Access the attributes on the selected feature, then display a callout containing that information. The above example uses a UILabel
to display the information.
If you would like to use a default callout, please see the handleMapTap
method on the dynamically style interactive points example. This example also creates a shape source from JSON data loaded at runtime.
Upvotes: 2