How show map annotations when map span will be 0.1? I want map pins to not show until map span is <= 0.1
struct City: Identifiable {
let id = UUID()
let name: String
let coordinate: CLLocationCoordinate2D
}
struct ContentView: View {
@State private var region = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 51.507222, longitude: -0.1275), span: MKCoordinateSpan(latitudeDelta: 10, longitudeDelta: 10))
let annotations = [
City(name: "London", coordinate: CLLocationCoordinate2D(latitude: 51.507222, longitude: -0.1275)),
City(name: "Paris", coordinate: CLLocationCoordinate2D(latitude: 48.8567, longitude: 2.3508)),
City(name: "Rome", coordinate: CLLocationCoordinate2D(latitude: 41.9, longitude: 12.5)),
City(name: "Washington DC", coordinate: CLLocationCoordinate2D(latitude: 38.895111, longitude: -77.036667))
]
var body: some View {
Map(coordinateRegion: $region, annotationItems: annotations) {
MapPin(coordinate: $0.coordinate)
}
.frame(width: 400, height: 300)
}
}
How can this be done?
CodePudding user response:
You can't with MapPin because it's a type of protocol
not View
. Instead of it you can use MapAnnotation
. Since your region
parameter is binding the view, you can check map span and show/hide your annotation like this;
Map(coordinateRegion: $region, annotationItems: annotations) {
MapAnnotation(coordinate: $0.coordinate) {
// Use whatever value instead of 2.5
if region.span.latitudeDelta < 2.5 {
Image(systemName: "mappin")
.resizable()
.frame(width: 18, height: 36)
.foregroundColor(Color.red)
} else {
EmptyView()
}
}
}
.frame(width: 400, height: 300)
CodePudding user response:
You can use a computed variable that returns true
when the span
is correct and then conditionally have the Map
use the annotations.
struct SuperZoomMap: View {
@State private var region = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 51.507222, longitude: -0.1275), span: MKCoordinateSpan(latitudeDelta: 10, longitudeDelta: 10))
let annotations = [
City(name: "London", coordinate: CLLocationCoordinate2D(latitude: 51.507222, longitude: -0.1275)),
City(name: "Paris", coordinate: CLLocationCoordinate2D(latitude: 48.8567, longitude: 2.3508)),
City(name: "Rome", coordinate: CLLocationCoordinate2D(latitude: 41.9, longitude: 12.5)),
City(name: "Washington DC", coordinate: CLLocationCoordinate2D(latitude: 38.895111, longitude: -77.036667))
]
///Returns true when the
///region.span.latitudeDelta <= 0.1 || region.span.longitudeDelta <= 0.1
var show: Bool{
if region.span.latitudeDelta <= 0.1 || region.span.longitudeDelta <= 0.1{
return true
}else{
return false
}
}
var body: some View {
VStack{
Text(region.span.latitudeDelta, format: .number)
Text(region.span.longitudeDelta, format: .number)
Map(coordinateRegion: $region, annotationItems: show ? annotations : []) {
MapPin(coordinate: $0.coordinate)
}
.frame(width: 400, height: 300)
}
}
}
You can also filter the pins using CLLocation
s distance
so you only plot pins within a certain distance of the center/ visible pins.
For example if you are zoomed into London exclude Paris, Rome and Washington DC.
struct SuperZoomMap: View {
@State private var region = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 51.507222, longitude: -0.1275), span: MKCoordinateSpan(latitudeDelta: 10, longitudeDelta: 10))
let annotations = [
City(name: "London", coordinate: CLLocationCoordinate2D(latitude: 51.507222, longitude: -0.1275)),
City(name: "Paris", coordinate: CLLocationCoordinate2D(latitude: 48.8567, longitude: 2.3508)),
City(name: "Rome", coordinate: CLLocationCoordinate2D(latitude: 41.9, longitude: 12.5)),
City(name: "Washington DC", coordinate: CLLocationCoordinate2D(latitude: 38.895111, longitude: -77.036667))
]
///Returns true when the
///region.span.latitudeDelta <= 0.1 || region.span.longitudeDelta <= 0.1
var show: Bool{
if region.span.latitudeDelta <= 0.1 || region.span.longitudeDelta <= 0.1{
return true
}else{
return false
}
}
//Only show the pins within 10000 meters from the center
var filtered: [City]{
guard show else {
return []
}
return annotations.filter { city in
let c = CLLocation(latitude: city.coordinate.latitude, longitude: city.coordinate.longitude)
let current = CLLocation(latitude: region.center.latitude, longitude: region.center.longitude)
return c.distance(from: current) <= 10000
}
}
var body: some View {
VStack{
Text(filtered.count, format: .number)
Text(region.span.latitudeDelta, format: .number)
Text(region.span.longitudeDelta, format: .number)
Map(coordinateRegion: $region, annotationItems: filtered) {
MapPin(coordinate: $0.coordinate)
}
.frame(width: 400, height: 300)
}
}
}