Custom Annotations

This example shows how to add custom annotations in MapView.

  • Add Annotations from GeoJson

  • Animate Annotations

  • Query Visible Annotations in Rect

  • Center Selected Annotation

docs-image

For all code examples, refer to Maps Code Examples

AnnotationsViewController view source

1
//
2
// StyleMapLayerViewController.swift
3
// maps-ios-demo
4
//
5
6
import Foundation
7
import UIKit
8
import Nbmap
9
10
enum AnnotationActionType{
11
case AddAnnotations
12
case AddNumberAnnotations
13
case AnimateAnnotations
14
case QueryVisibleAnnotations
15
case CenterSelectedAnnotations
16
case AddVisibleAreaPolyline
17
18
}
19
20
class AnnotationsViewController: UIViewController {
21
22
var nbMapView: NGLMapView! {
23
didSet {
24
oldValue?.removeFromSuperview()
25
if let mapView = nbMapView {
26
view.insertSubview(mapView, at: 0)
27
mapView.delegate = self
28
}
29
}
30
}
31
var button: UIButton!
32
33
let typeList = [
34
AnnotationActionType.AddAnnotations,
35
AnnotationActionType.AddNumberAnnotations,
36
AnnotationActionType.AnimateAnnotations,
37
AnnotationActionType.QueryVisibleAnnotations,
38
AnnotationActionType.CenterSelectedAnnotations,
39
AnnotationActionType.AddVisibleAreaPolyline,
40
]
41
42
43
var points : Array = [CLLocationCoordinate2D]()
44
45
override func viewDidLoad() {
46
super.viewDidLoad()
47
nbMapView = NGLMapView(frame:self.view.bounds)
48
button = UIButton(type: .system)
49
button.setTitle("Settings", for: .normal)
50
button.addTarget(self, action: #selector(showSetings), for: .touchUpInside)
51
button.frame = CGRect(x: 0, y: 0, width: 100, height: 40)
52
navigationItem.rightBarButtonItem = UIBarButtonItem(customView: button)
53
}
54
55
@objc func showSetings() {
56
let tableViewController = UITableViewController(style: .plain)
57
tableViewController.tableView.delegate = self
58
tableViewController.tableView.dataSource = self
59
tableViewController.title = "Camera Settings"
60
self.present(tableViewController, animated: true)
61
}
62
63
func performeSettings(type: AnnotationActionType) {
64
switch type {
65
case AnnotationActionType.AddAnnotations :
66
addAnnotations(count: 100)
67
break
68
case AnnotationActionType.AddNumberAnnotations :
69
addAnnotations(count: 1000)
70
break
71
case .AnimateAnnotations:
72
animateAnnotations()
73
break
74
case .QueryVisibleAnnotations:
75
queryVisibleAnnotations()
76
break
77
case .CenterSelectedAnnotations:
78
centerSelectedAnnotation()
79
break
80
case .AddVisibleAreaPolyline:
81
addVisibleAreaPolyline()
82
break
83
}
84
85
}
86
87
func addAnnotations(count: Int32) {
88
89
if let annotations = self.nbMapView.annotations {
90
self.nbMapView.removeAnnotations(annotations)
91
}
92
93
DispatchQueue.global(qos: .default).async {
94
if let featuresData = try? Data(contentsOf: Bundle.main.url(forResource: "points", withExtension: "geojson")!),
95
let features = try? JSONSerialization.jsonObject(with: featuresData, options: []) as? [String: Any] {
96
97
var annotations = [NGLPointAnnotation]()
98
99
if let featureList = features["features"] as? [[String: Any]] {
100
for feature in featureList {
101
if let coordinates = feature["geometry"] as? [String: Any],
102
let coordinateList = coordinates["coordinates"] as? [Double],
103
let title = feature["properties"] as? [String: Any] {
104
105
let coordinate = CLLocationCoordinate2D(latitude: coordinateList[1], longitude: coordinateList[0])
106
let annotation = NGLPointAnnotation()
107
annotation.coordinate = coordinate
108
annotation.title = title["NAME"] as? String
109
110
annotations.append(annotation)
111
112
if annotations.count == count {
113
break
114
}
115
}
116
}
117
118
DispatchQueue.main.async {
119
self.nbMapView.addAnnotations(annotations)
120
self.nbMapView.showAnnotations(annotations, animated: true)
121
}
122
}
123
}
124
}
125
126
}
127
128
func animateAnnotations () {
129
let annot = NGLPointAnnotation()
130
annot.coordinate = self.nbMapView.centerCoordinate
131
self.nbMapView.addAnnotation(annot)
132
133
let point = CGPoint(x: self.view.frame.origin.x + 200, y: self.view.frame.midY)
134
let coord = self.nbMapView.convert(point, toCoordinateFrom: self.view)
135
136
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
137
UIView.animate(withDuration: 1) {
138
annot.coordinate = coord
139
}
140
}
141
142
}
143
144
func queryVisibleAnnotations() {
145
let visibleAnnotationCount = NSNumber(value: self.nbMapView.visibleAnnotations?.count ?? 0)
146
var message: String
147
148
if visibleAnnotationCount.intValue == 1 {
149
message = "There is \(visibleAnnotationCount) visible annotation."
150
} else {
151
message = "There are \(visibleAnnotationCount) visible annotations."
152
}
153
154
let alertController = UIAlertController(title: "Visible Annotations", message: message, preferredStyle: .alert)
155
alertController.addAction(UIAlertAction(title: "Ok", style: .cancel, handler: nil))
156
self.present(alertController, animated: true, completion: nil)
157
158
}
159
160
func centerSelectedAnnotation() {
161
162
if let annotation = self.nbMapView.selectedAnnotations.first {
163
let point = self.nbMapView.convert(annotation.coordinate, toPointTo: self.nbMapView)
164
let center = self.nbMapView.convert(point, toCoordinateFrom: self.nbMapView)
165
self.nbMapView.setCenter(center, animated: true)
166
}
167
}
168
169
func addVisibleAreaPolyline() {
170
let constrainedRect = self.nbMapView.bounds.inset(by: self.nbMapView.contentInset)
171
172
var lineCoords = [CLLocationCoordinate2D]()
173
174
lineCoords.append(self.nbMapView.convert(CGPoint(x: constrainedRect.minX, y: constrainedRect.minY), toCoordinateFrom: self.nbMapView))
175
lineCoords.append(self.nbMapView.convert(CGPoint(x: constrainedRect.maxX, y: constrainedRect.minY), toCoordinateFrom: self.nbMapView))
176
lineCoords.append(self.nbMapView.convert(CGPoint(x: constrainedRect.maxX, y: constrainedRect.maxY), toCoordinateFrom: self.nbMapView))
177
lineCoords.append(self.nbMapView.convert(CGPoint(x: constrainedRect.minX, y: constrainedRect.maxY), toCoordinateFrom: self.nbMapView))
178
lineCoords.append(lineCoords[0])
179
180
let line = NGLPolyline(coordinates: &lineCoords, count: UInt(lineCoords.count))
181
self.nbMapView.addAnnotation(line)
182
183
}
184
185
186
}
187
188
189
extension AnnotationsViewController: NGLMapViewDelegate {
190
func mapView(_ mapView: NGLMapView, didFinishLoading style: NGLStyle){
191
nbMapView.setCenter(CLLocationCoordinate2DMake(38.87031006108791, -77.00896639534831), zoomLevel: 10, animated: true)
192
193
}
194
195
func mapView(_ mapView: NGLMapView, didSelect annotation: NGLAnnotation) {
196
let point = self.nbMapView.convert(annotation.coordinate, toPointTo: self.nbMapView)
197
let center = self.nbMapView.convert(point, toCoordinateFrom: self.nbMapView)
198
self.nbMapView.setCenter(center, zoomLevel: 14, animated: true)
199
}
200
201
func mapView(_ mapView: NGLMapView, annotationCanShowCallout annotation: NGLAnnotation) -> Bool {
202
return true
203
}
204
}
205
206
extension AnnotationsViewController: UITableViewDelegate, UITableViewDataSource {
207
208
func settingsTitlesForRaw(index: Int) -> String {
209
let type = typeList[index]
210
switch type {
211
case AnnotationActionType.AddAnnotations :
212
return "Add 100 Annotations"
213
case AnnotationActionType.AddNumberAnnotations :
214
return "Add 1000 Annotations"
215
case AnnotationActionType.AnimateAnnotations :
216
return "Animate Annotations"
217
case AnnotationActionType.QueryVisibleAnnotations :
218
return "Query Visible Annotations"
219
case AnnotationActionType.CenterSelectedAnnotations :
220
return "Center Selected Annotations"
221
case AnnotationActionType.AddVisibleAreaPolyline :
222
return "Add Visible Area Polyline"
223
}
224
}
225
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
226
return typeList.count
227
}
228
229
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
230
let cell = UITableViewCell(style: .default, reuseIdentifier: nil)
231
cell.textLabel?.text = settingsTitlesForRaw(index: indexPath.row)
232
return cell
233
}
234
235
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
236
tableView.isHidden = true
237
let type = typeList[indexPath.row]
238
dismissSettings(type: type)
239
}
240
241
func dismissSettings(type: AnnotationActionType) {
242
dismiss(animated: true)
243
performeSettings(type: type)
244
}
245
}
  1. Initializing nbMapView:

    • The nbMapView is initialized with a frame that matches the bounds of the view controller's view.

    • The mapView is added as a subview of the view controller's view and set as the delegate of the map view.

  2. addAnnotations:

    • Removes any existing annotations from the map view.

    • Asynchronously loads a GeoJSON file named "points.geojson" from the main bundle.

    • Parses the GeoJSON data and extracts the coordinates and title for each feature.

    • Creates NGLPointAnnotation objects for each feature and adds them to an array.

    • Adds the annotations to the map view and shows them with an animated effect.

3 queryVisibleAnnotations:

  • Retrieves the count of visible annotations on the map view using nbMapView.visibleAnnotations.

  • Displays an alert controller with a message indicating the number of visible annotations.

  1. centerSelectedAnnotation:

    • Checks if there is a selected annotation on the map view using nbMapView.selectedAnnotations.

    • Converts the coordinate of the selected annotation to a point on the map view.

    • Converts the point to a coordinate on the map view.

    • Sets the map view's center coordinate to the new coordinate with an animated effect using nbMapView.setCenter(center, animated: true).

4 addVisibleAreaPolyline:

  • Creates a rectangle (constrainedRect) that represents the visible area of the map view.

  • Converts the four corners of the rectangle to coordinates on the map view.

  • Creates an NGLPolyline with the converted coordinates and adds it as an annotation to the map view.

© 2024 NextBillion.ai all rights reserved.