I want to add a moving circle on MKMapView it will remain in the centre of the map and start moving when the user moves the map and zoom in and zoom out when the user zooms in/out the map I am able to achieve this by using the centre coordinate of the map but when I move the app it is flickering as I am removing and adding the MKCircle overlay when the coordinate changes
What I want to achieve:- A moving circle/Annotation on top of the mapview which moves/zoom along with mapview
Here is the code
Adding pan gesture and circle overlay here
func makeUIView(context: Context) -> MKMapView {
let mapView = MKMapView()
mapView.delegate = context.coordinator
mapView.isUserInteractionEnabled = true
mapView.showsUserLocation = true
mapView.showsCompass = false
let panGesture = UIPanGestureRecognizer(target: context.coordinator, action: #selector(context.coordinator.addPinBasedOnGesture(_:)))
panGesture.delegate = context.coordinator
mapView.addGestureRecognizer(panGesture)
return mapView
}
Adding and removing method which updated the moving circle coordinate to
func updateMovingCircle(regionToUpdate: MKCoordinateRegion, view: MKMapView) {
DispatchQueue.main.async {
addMovingCircle(to: view, movingLocation: CLLocationCoordinate2D(latitude: regionToUpdate.center.latitude, longitude: regionToUpdate.center.longitude), radius: radius)
}
}
func to add and remove circle
func addMovingCircle(to view: MKMapView, movingLocation: CLLocationCoordinate2D, radius: Int) {
for overlay in overlays where overlay.title == "1" {
view.removeOverlay(overlay)
}
let radius: Double = Double(radius) * 1.5
let movingCircle = MKCircle(center: movingLocation, radius: radius * 1000)
movingCircle.title = "1"
view.addOverlay(movingCircle)
}
gesture recognizer delegate method on coordinator
@objc func addPinBasedOnGesture(_ gestureRecognizer: UIGestureRecognizer) {
if let mapView = gestureRecognizer.view as? MKMapView {
mapViewController.updateMovingCircle(regionToUpdate: mapView.region, view: mapView)
}
}
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
return true
}
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
Overlay renderer
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
if let circleOverlay = overlay as? MKCircle {
let circleRenderer = MKCircleRenderer(overlay: circleOverlay)
circleRenderer.strokeColor = UIColor(Color.SG.purple)
circleRenderer.lineWidth = 2
circleRenderer.lineDashPattern = [2, 5]
return circleRenderer
}
return MKOverlayRenderer()
}
This code is working but the experience is not smooth and circle is flickering
I would like to go with a different approach. You can add the entire MapView inside a ZStack and a
MKCircleabove the map. Then, no matter how you interact with the map, MKCircle will stay at the center.Updated: Here is the idea for zoom action
You may want to change the view size or add animation if needed. Output looks like this: