如何使地图路线说明在 SwiftUI 上可点击?
How can I make map route instructions clickable on SwiftUI?
我有一张用“纯”SwiftUI 制作的简单地图。有一个用于搜索地点的搜索栏,当我单击“前往”按钮时,它会显示如何从特定位置前往该地点的说明。它显示在地图下方的“输入目的地”字段中。我想要做的是,我希望这些说明是可点击的。当我单击每条说明时,它应该放大说明发生的特定位置。现在它只是一个文本列表。不使用 UIViewRepresentable 是否可以做到这一点?我该怎么做?
我试过
.onTapGesture {
region.span = MKCoordinateSpan(latitudeDelta: region.span.latitudeDelta/2, longitudeDelta: region.span.longitudeDelta/2)
}
但它会在我点击的每条指令上放大相同的位置。
内容视图
struct Location: Identifiable {
let id = UUID()
let name: String
let coordinate: CLLocationCoordinate2D
}
struct RouteSteps: Identifiable {
let id = UUID()
let step: String
}
struct ContentView: View {
@State private var searchBar: String = ""
@State private var home = CLLocationCoordinate2D(latitude: 39.90068, longitude: 32.86081)
@State private var region = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 39.90068, longitude: 32.86081), span: MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05))
@State var routeSteps: [RouteSteps] = [RouteSteps(step: "Enter a destination")]
@State var annotations = [Location(name: "Ankara", coordinate: CLLocationCoordinate2D(latitude: 39.90068, longitude: 32.86081))]
var body: some View {
VStack{
HStack {
TextField("", text: $searchBar)
Button("Go") {
findNewLocation()
}
.frame(width: 35, height: 35)
.foregroundColor(Color.white)
.background(Color.blue)
.cornerRadius(5)
}.textFieldStyle(.roundedBorder).colorInvert()
Map(coordinateRegion: $region, annotationItems: annotations){ item in
MapMarker(coordinate: item.coordinate)
}.frame(width: 400, height: 300)
List(routeSteps) { r in
Text(r.step)
}
ContentView 中的路由功能
func findNewLocation(){
let searchResult = searchBar
let geocoder = CLGeocoder()
geocoder.geocodeAddressString(searchResult, completionHandler:
{(placemarks, error) -> Void in
if((error) != nil){
print("error at geocode")
}
if let placemark = placemarks?.first {
let coordinates : CLLocationCoordinate2D = placemark.location!.coordinate
region = MKCoordinateRegion(center: coordinates, span: MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05))
annotations.append(Location(name: placemark.name!, coordinate: coordinates))
let request = MKDirections.Request()
request.source = MKMapItem(placemark: MKPlacemark(coordinate: home, addressDictionary: nil))
request.destination = MKMapItem(placemark: MKPlacemark(coordinate: coordinates, addressDictionary: nil))
request.requestsAlternateRoutes = false
request.transportType = .automobile
let directions = MKDirections(request: request)
directions.calculate(completionHandler: { response, error in
for route in (response?.routes)! {
self.routeSteps = []
for step in route.steps {
self.routeSteps.append(RouteSteps(step: step.instructions))
}
}
})
}
})
}
是的,但是您必须停止丢弃数据。 MKRoute.Steps
实际上给了你所有你需要的信息,所以首先,设置 RouteSteps
接受 MKRoute.Steps
:
struct RouteSteps: Identifiable {
let id = UUID()
let step: MKRoute.Step
}
然后,在您的 findNewLocation()
函数中:
func findNewLocation(){
...
directions.calculate(completionHandler: { response, error in
// I used a guard statement to get rid of your force unwrap.
// NEVER force unwrap in a situation like this.
// Implement error handling here
guard let response = response else { return }
for route in response.routes {
// Map the MKRoute.Steps to your struct
self.routeSteps = route.steps.map( { RouteSteps(step: [=11=]) } )
}
})
...
}
然后在你的主要部分ContentView
:
struct ContentView: View {
...
var body: some View {
...
List(routeSteps) { routeStep in
// Pull your instructions out here
Text(routeStep.step.instructions)
.onTapGesture {
// The MKRoute.Step contains an overlay polyline for MKMapKit.
// We can't use that in SwiftUI maps yet, but the polyline contains a
// boundingMapRect that we can use to change the region shown on the map
// with the MKCoordinateRegion(_ MKMapRect) initializer. Setting the region
// to the insturction's polyline boundingMapRect does exactly what you want.
region = MKCoordinateRegion(routeStep.step.polyline.boundingMapRect)
}
}
...
}
我有一张用“纯”SwiftUI 制作的简单地图。有一个用于搜索地点的搜索栏,当我单击“前往”按钮时,它会显示如何从特定位置前往该地点的说明。它显示在地图下方的“输入目的地”字段中。我想要做的是,我希望这些说明是可点击的。当我单击每条说明时,它应该放大说明发生的特定位置。现在它只是一个文本列表。不使用 UIViewRepresentable 是否可以做到这一点?我该怎么做?
我试过
.onTapGesture {
region.span = MKCoordinateSpan(latitudeDelta: region.span.latitudeDelta/2, longitudeDelta: region.span.longitudeDelta/2)
}
但它会在我点击的每条指令上放大相同的位置。
内容视图
struct Location: Identifiable {
let id = UUID()
let name: String
let coordinate: CLLocationCoordinate2D
}
struct RouteSteps: Identifiable {
let id = UUID()
let step: String
}
struct ContentView: View {
@State private var searchBar: String = ""
@State private var home = CLLocationCoordinate2D(latitude: 39.90068, longitude: 32.86081)
@State private var region = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 39.90068, longitude: 32.86081), span: MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05))
@State var routeSteps: [RouteSteps] = [RouteSteps(step: "Enter a destination")]
@State var annotations = [Location(name: "Ankara", coordinate: CLLocationCoordinate2D(latitude: 39.90068, longitude: 32.86081))]
var body: some View {
VStack{
HStack {
TextField("", text: $searchBar)
Button("Go") {
findNewLocation()
}
.frame(width: 35, height: 35)
.foregroundColor(Color.white)
.background(Color.blue)
.cornerRadius(5)
}.textFieldStyle(.roundedBorder).colorInvert()
Map(coordinateRegion: $region, annotationItems: annotations){ item in
MapMarker(coordinate: item.coordinate)
}.frame(width: 400, height: 300)
List(routeSteps) { r in
Text(r.step)
}
ContentView 中的路由功能
func findNewLocation(){
let searchResult = searchBar
let geocoder = CLGeocoder()
geocoder.geocodeAddressString(searchResult, completionHandler:
{(placemarks, error) -> Void in
if((error) != nil){
print("error at geocode")
}
if let placemark = placemarks?.first {
let coordinates : CLLocationCoordinate2D = placemark.location!.coordinate
region = MKCoordinateRegion(center: coordinates, span: MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05))
annotations.append(Location(name: placemark.name!, coordinate: coordinates))
let request = MKDirections.Request()
request.source = MKMapItem(placemark: MKPlacemark(coordinate: home, addressDictionary: nil))
request.destination = MKMapItem(placemark: MKPlacemark(coordinate: coordinates, addressDictionary: nil))
request.requestsAlternateRoutes = false
request.transportType = .automobile
let directions = MKDirections(request: request)
directions.calculate(completionHandler: { response, error in
for route in (response?.routes)! {
self.routeSteps = []
for step in route.steps {
self.routeSteps.append(RouteSteps(step: step.instructions))
}
}
})
}
})
}
是的,但是您必须停止丢弃数据。 MKRoute.Steps
实际上给了你所有你需要的信息,所以首先,设置 RouteSteps
接受 MKRoute.Steps
:
struct RouteSteps: Identifiable {
let id = UUID()
let step: MKRoute.Step
}
然后,在您的 findNewLocation()
函数中:
func findNewLocation(){
...
directions.calculate(completionHandler: { response, error in
// I used a guard statement to get rid of your force unwrap.
// NEVER force unwrap in a situation like this.
// Implement error handling here
guard let response = response else { return }
for route in response.routes {
// Map the MKRoute.Steps to your struct
self.routeSteps = route.steps.map( { RouteSteps(step: [=11=]) } )
}
})
...
}
然后在你的主要部分ContentView
:
struct ContentView: View {
...
var body: some View {
...
List(routeSteps) { routeStep in
// Pull your instructions out here
Text(routeStep.step.instructions)
.onTapGesture {
// The MKRoute.Step contains an overlay polyline for MKMapKit.
// We can't use that in SwiftUI maps yet, but the polyline contains a
// boundingMapRect that we can use to change the region shown on the map
// with the MKCoordinateRegion(_ MKMapRect) initializer. Setting the region
// to the insturction's polyline boundingMapRect does exactly what you want.
region = MKCoordinateRegion(routeStep.step.polyline.boundingMapRect)
}
}
...
}