谷歌MapIOS-Swift上的虚线折线

v1uwarro  于 2022-12-10  发布在  Swift
关注(0)|答案(4)|浏览(187)

我想在谷歌Map上用swift语言画一条虚线折线,有人能帮我吗?

4bbkushb

4bbkushb1#

private var polylineArray:[GMSCircle] = [GMSCircle]() //global variable

//MARK: Find a route between to coordinates and draw the route

private func callingDistanceAPI() {
   let origin = "\(37.778483),\(-122.513960)"
   let destination = "\(37.706753),\(-122.418677)"
   let url = "https://maps.googleapis.com/maps/api/directions/json?origin=\(origin)&destination=\(destination)&mode=driving&key=[YOUR-API-KEY]"

Alamofire.request(url).responseJSON { response in
   guard let data = response as? [String:Any],
            let preRoutes = data["routes"] as? NSArray,
            let preRoute = preRoutes.firstObject,
            let routes = preRoute as? NSDictionary,
            let routeOverviewPolyline:NSDictionary = routes.value(forKey: "overview_polyline") as? NSDictionary,
            let polyString = routeOverviewPolyline.object(forKey: "points") as? String else {
            return
        }
      self.showPath(polyStr: polyString)
    }
}


//MARK: Draw polyline

func showPath(polyStr :String) {
    guard let path = GMSMutablePath(fromEncodedPath: polyStr) else {return}
    //MARK: remove the old polyline from the GoogleMap
    self.removePolylinePath()

    let intervalDistanceIncrement: CGFloat = 10
    let circleRadiusScale = 1 / mapView.projection.points(forMeters: 1, at: mapView.camera.target)
    var previousCircle: GMSCircle?
    for coordinateIndex in 0 ..< path.count() - 1 {
        let startCoordinate = path.coordinate(at: coordinateIndex)
        let endCoordinate = path.coordinate(at: coordinateIndex + 1)
        let startLocation = CLLocation(latitude: startCoordinate.latitude, longitude: startCoordinate.longitude)
        let endLocation = CLLocation(latitude: endCoordinate.latitude, longitude: endCoordinate.longitude)
        let pathDistance = endLocation.distance(from: startLocation)
        let intervalLatIncrement = (endLocation.coordinate.latitude - startLocation.coordinate.latitude) / pathDistance
        let intervalLngIncrement = (endLocation.coordinate.longitude - startLocation.coordinate.longitude) / pathDistance
        for intervalDistance in 0 ..< Int(pathDistance) {
            let intervalLat = startLocation.coordinate.latitude + (intervalLatIncrement * Double(intervalDistance))
            let intervalLng = startLocation.coordinate.longitude + (intervalLngIncrement * Double(intervalDistance))
            let circleCoordinate = CLLocationCoordinate2D(latitude: intervalLat, longitude: intervalLng)
            if let previousCircle = previousCircle {
                let circleLocation = CLLocation(latitude: circleCoordinate.latitude,
                                                longitude: circleCoordinate.longitude)
                let previousCircleLocation = CLLocation(latitude: previousCircle.position.latitude,
                                                        longitude: previousCircle.position.longitude)
                if mapView.projection.points(forMeters: circleLocation.distance(from: previousCircleLocation),
                                             at: mapView.camera.target) < intervalDistanceIncrement {
                    continue
                }
            }
            let circleRadius = 3 * CLLocationDistance(circleRadiusScale)
            let circle = GMSCircle(position: circleCoordinate, radius: circleRadius)
            circle.strokeWidth = 1.0
            circle.strokeColor = UIColor.Yulu.blue
            circle.fillColor = UIColor.Yulu.blue
            circle.map = mapView
            circle.userData = "root"
            polylineArray.append(circle)
            previousCircle = circle
        }
    }
}

    //MARK: - Removing dotted polyline 
    func removePolylinePath() {
    for root: GMSCircle in self.polylineArray {
        if let userData = root.userData as? String,
            userData == "root" {
            root.map = nil
        }
    }
}

我已从以下链接获取绘制虚线折线的参考:https://engineering.door2door.io/dotted-polylines-with-google-maps-sdk-for-ios-7b21786a0645

k2fxgqgv

k2fxgqgv2#

我基于@ Purnenduroy的代码实现了一个如下所示的虚线折线。
Dotted polyline example

private var polylineArray = [GMSMarker]()
var lastZoom: Float = 0
var walkingPathData = [[Double]]()
var kvoToken: NSKeyValueObservation?

override func viewDidAppear(_ animated: Bool) {

    super.viewDidAppear(animated)
    
    self.kvoToken = self.mapView.observe(\.camera.zoom, options: .new) { [weak self] mapView, change in
        guard let self else { return }
        guard let currentZoom = change.newValue else { return }
        
        if abs(self.lastZoom - currentZoom) >= 0.35 {
            self.lastZoom = currentZoom
            self.drawWalkingPath()
        }
    }
}

override func viewDidDisappear(_ animated: Bool) {
    super.viewDidDisappear(animated)
    self.kvoToken?.invalidate()
    self.kvoToken = nil
}

我创建了一个KVO令牌来观察Map的缩放值,以便在缩放值改变时重新绘制路径。没有用于缩放改变的GMSMapViewDelegate方法。我用0.35的阈值限制了重新绘制。

func getWalkingPath() {
        self.viewModel.calculateWalkingPath(from: fromLocation, to: toLocation) { [weak self] model, errorMessage in
            guard let self else { return }
            if let model {
                self.walkingPathData = model.pathLocations // [[Double]]
                self.drawWalkingPath()
            }
        }
    }

    //MARK: - Drawing dotted polyline
    func drawWalkingPath() {
        let path = GMSMutablePath()
        for item in self.walkingPathData {
            let location = CLLocationCoordinate2D(latitude: item[0], longitude: item[1])
            path.add(location)
        }
        
        self.removePolylinePath()
        
        let intervalDistanceIncrement: CGFloat = 12
        var previousMarker: GMSMarker?
        guard path.count() > 0 else { return }
        for coordinateIndex in 0 ..< path.count() - 1 {
            let startCoordinate = path.coordinate(at: coordinateIndex)
            let endCoordinate = path.coordinate(at: coordinateIndex + 1)
            let startLocation = CLLocation(latitude: startCoordinate.latitude, longitude: startCoordinate.longitude)
            let endLocation = CLLocation(latitude: endCoordinate.latitude, longitude: endCoordinate.longitude)
            let pathDistance = endLocation.distance(from: startLocation)
            let intervalLatIncrement = (endLocation.coordinate.latitude - startLocation.coordinate.latitude) / pathDistance
            let intervalLngIncrement = (endLocation.coordinate.longitude - startLocation.coordinate.longitude) / pathDistance
            for intervalDistance in 0 ..< Int(pathDistance) {
                let intervalLat = startLocation.coordinate.latitude + (intervalLatIncrement * Double(intervalDistance))
                let intervalLng = startLocation.coordinate.longitude + (intervalLngIncrement * Double(intervalDistance))
                let markerCoordinate = CLLocationCoordinate2D(latitude: intervalLat, longitude: intervalLng)
                if let previousMarker = previousMarker {
                    let markerLocation = CLLocation(latitude: markerCoordinate.latitude,
                                                    longitude: markerCoordinate.longitude)
                    let previousMarkerLocation = CLLocation(latitude: previousMarker.position.latitude,
                                                            longitude: previousMarker.position.longitude)
                    if mapView.projection.points(forMeters: markerLocation.distance(from: previousMarkerLocation),
                                                 at: mapView.camera.target) < intervalDistanceIncrement {
                        continue
                    }
                }
                let marker = GMSMarker(position: markerCoordinate)
                let dotView = UIView(frame: CGRect(x: 0, y: 0, width: 9, height: 9))
                dotView.corner(dotView.frame.size.height/2)
                dotView.backgroundColor = .systemBlue
                marker.iconView = dotView
                marker.map = mapView
                marker.userData = "dottedPath"
                polylineArray.append(marker)
                previousMarker = marker
            }
        }
    }
    
    //MARK: - Removing dotted polyline
    func removePolylinePath() {
        for root: GMSMarker in self.polylineArray {
            if let userData = root.userData as? String,
               userData == "dottedPath" {
                root.map = nil
            }
        }
    }

我使用了GMSMarker沿着基于UIView的圆圈,而不是GMSCircle。因此,我实现了无论缩放级别如何都有静态大小的圆圈。当放大时,点的频率将增加,否则反之亦然。
要增加点之间的距离,请增加intervalDistanceIncrement值;要编辑点,可以更改UIView对象的大小和背景颜色。

ddhy6vgd

ddhy6vgd3#

参考以下链接:http://www.appcoda.com/google-maps-api-tutorial/可能有帮助。

func drawRoute() {
    let route = mapTasks.overviewPolyline["points"] as String

    let path: GMSPath = GMSPath(fromEncodedPath: route)
    routePolyline = GMSPolyline(path: path)
    routePolyline.map = viewMap
}

在上述代码片段的结尾,我们必须将Map设置为routePolyline属性。

func displayRouteInfo() {
    lblInfo.text = mapTasks.totalDistance + "\n" + mapTasks.totalDuration
}
yhxst69z

yhxst69z4#

据我所知,这是不可能的:-(。你可以通过GMSStyleSpans画虚线,但不是虚线(谷歌Map版本2.2.0)。如果我错了,请留下评论。

相关问题