在 MapKit 中循环路线

问题描述 投票:0回答:1

我目前正在学习 Swift(在 Xcode 中),并且正在尝试制作一个应用程序。我一直在按照教程在 Mapkit 中制作路线。

目前,我拥有它,以便用户可以输入一个位置,它会创建一条到该位置的路线。有什么办法可以让它创建一个循环吗?

基本上会发生的情况是,它会映射一条到该位置的路线(例如地址、星巴克等),然后掉头继续沿着路线回到起点(但不只是以同样的方式穿越回去,它会覆盖不同的街道)。

希望这是有道理的,这是我的代码:

//
//  ContentView.swift
//  NavNinja
//
//  Created by Dakota on 2/11/24.
//


import SwiftUI
import MapKit


struct ContentView: View {
    @State private var cameraPosition: MapCameraPosition = .region(.userRegion)
    @State private var searchText = ""
    @State private var results = [MKMapItem]()
    @State private var mapSelection: MKMapItem?
    @State private var showDetails = false
    @State private var getDirections = false
    
    //ROUTE
    @State private var routeDisplaying = false
    @State private var route: MKRoute?
    @State private var routeDestination: MKMapItem?
    @State private var routeDistanceInMiles: Double = 0.0
    //ROUTE
    
    var body: some View {
        Map(position: $cameraPosition, selection: $mapSelection) {
            
            UserAnnotation()
            Annotation("My location", coordinate: .userLocation) {
                ZStack {
                    Circle()
                        .frame(width: 32, height: 32)
                        .foregroundStyle(.blue.opacity(0.25))
                    
                    Circle()
                        .frame(width: 20, height: 20)
                        .foregroundStyle(.white)
                    
                    Circle()
                        .frame(width: 12, height: 12)
                        .foregroundStyle(.blue)
                }
            }
            
            ForEach(results, id: \.self) { item in
                if routeDisplaying {
                    if item == routeDestination {
                        let placemark = item.placemark
                        Marker(placemark.name ?? "", coordinate: placemark.coordinate)
                    }
                } else {
                    let placemark = item.placemark
                    Marker(placemark.name ?? "", coordinate: placemark.coordinate)
                }
            }
            
            //ROUTE
            if let route {
                MapPolyline(route.polyline)
                    .stroke(.blue, lineWidth: 6)
            }
            //ROUTE
        }
        .overlay(alignment: .top) {
            TextField("Search for a location...", text: $searchText)
                .font(.subheadline)
                .padding(22)
                .background(.white)
                .padding()
                .shadow(radius: 10)
        }
        
        // Add route distance display
                    .overlay(alignment: .bottomTrailing) {
                        if route != nil {
                            Text(String(format: "Route Distance: %.2f miles", routeDistanceInMiles))
                                .font(.footnote)
                                .foregroundColor(.white)
                                .padding(8)
                                .background(Color.black.opacity(0.7))
                                .cornerRadius(8)
                                .padding(10)
                        }
                    }
        
        .onSubmit(of: /*@START_MENU_TOKEN@*/.text/*@END_MENU_TOKEN@*/) {
            Task { await searchPlaces() }
        }
        //ROUTE
        .onChange(of: getDirections, { oddValue, newValue in
            if newValue {
                fetchRoute()
            }
        })
        //ROUTE
        .onChange(of: mapSelection, { addValue, newValue in
            showDetails = newValue != nil
        })
        .sheet(isPresented: $showDetails, content: {
            LocationDetailsView(mapSelection: $mapSelection,
                                show: $showDetails,
                                getDirections: $getDirections)
                .presentationDetents([.height(340)])
                .presentationBackgroundInteraction(.enabled(upThrough: .height(340)))
                .presentationCornerRadius(12)
        })
        .mapControls {
            MapCompass()
            MapPitchToggle()
            MapUserLocationButton()
        }
    }
}
extension ContentView {
    func searchPlaces() async {
        let request = MKLocalSearch.Request()
        request.naturalLanguageQuery = searchText
        request.region = .userRegion
        let results = try? await MKLocalSearch(request: request).start()
        self.results = results?.mapItems ?? []
    }
    
    //ROUTE
    func fetchRoute() {
        if let mapSelection {
            let request = MKDirections.Request()
            request.source = MKMapItem(placemark: .init(coordinate: .userLocation))
            request.destination    = mapSelection
            
            Task {
                let result = try? await MKDirections(request: request).calculate()
                route = result?.routes.first
                routeDestination = mapSelection
                
                withAnimation(.snappy) {
                    routeDisplaying = true
                    showDetails = false
                    
                    if let rect = route?.polyline.boundingMapRect, routeDisplaying {
                        cameraPosition = .rect(rect)
                    }
                    
                    // Calculate the total distance of the route in miles
                    if let totalDistanceInMeters = route?.distance {
                        // Convert meters to miles
                        let totalDistanceInMiles = totalDistanceInMeters / 1609.34 // 1 mile = 1609.34 meters
                        routeDistanceInMiles = totalDistanceInMiles
                    }
                    
                }
            }
        }
    }
    //ROUTE
}
extension CLLocationCoordinate2D {
    static var userLocation: CLLocationCoordinate2D {
        return .init(latitude: 25.7602, longitude: -80.1959)
    }
}
extension MKCoordinateRegion {
    static var userRegion: MKCoordinateRegion {
        return .init(center: .userLocation,
        latitudinalMeters: 1000,
        longitudinalMeters: 1000)
    }
}
#Preview {
    ContentView()
}

两个“//ROUTE”注释之间的所有代码都表明该代码与映射路线有关。

swiftui mapkit
1个回答
0
投票

使用 MKRoute.Step 在路线中添加步骤以强制使用不同方向的循环 每个 MKRoute.Step 对象都对应于人们在两点之间导航时需要遵循的单个指令。例如,一个步骤可能涉及沿着一条道路行驶,直到继续沿该路线需要转弯为止。

© www.soinside.com 2019 - 2024. All rights reserved.