我想在谷歌Map上用swift语言画一条虚线折线,有人能帮我吗?
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
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对象的大小和背景颜色。
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 }
yhxst69z4#
据我所知,这是不可能的:-(。你可以通过GMSStyleSpans画虚线,但不是虚线(谷歌Map版本2.2.0)。如果我错了,请留下评论。
4条答案
按热度按时间4bbkushb1#
我已从以下链接获取绘制虚线折线的参考:https://engineering.door2door.io/dotted-polylines-with-google-maps-sdk-for-ios-7b21786a0645
k2fxgqgv2#
我基于@ Purnenduroy的代码实现了一个如下所示的虚线折线。
Dotted polyline example
我创建了一个KVO令牌来观察Map的缩放值,以便在缩放值改变时重新绘制路径。没有用于缩放改变的GMSMapViewDelegate方法。我用0.35的阈值限制了重新绘制。
我使用了GMSMarker沿着基于UIView的圆圈,而不是GMSCircle。因此,我实现了无论缩放级别如何都有静态大小的圆圈。当放大时,点的频率将增加,否则反之亦然。
要增加点之间的距离,请增加intervalDistanceIncrement值;要编辑点,可以更改UIView对象的大小和背景颜色。
ddhy6vgd3#
参考以下链接:http://www.appcoda.com/google-maps-api-tutorial/可能有帮助。
在上述代码片段的结尾,我们必须将Map设置为routePolyline属性。
yhxst69z4#
据我所知,这是不可能的:-(。你可以通过GMSStyleSpans画虚线,但不是虚线(谷歌Map版本2.2.0)。如果我错了,请留下评论。