代码之家  ›  专栏  ›  技术社区  ›  mrkot

如何使注释在地图上平滑移动(调整其坐标)?

  •  0
  • mrkot  · 技术社区  · 6 年前

    我是一个新手Swift开发,我正在建立一个应用程序,跟踪城市巴士在地图上的位置。

    到目前为止,我的应用程序正在检索一个JSON,它被解码成一个遵循MKAnnotation协议的对象数组。

    然后我用这个方法在地图上显示它们:

    func updateUI(json: MyModelClass) {
        mapView.removeAnnotations(mapView.annotations)
        mapView.addAnnotations(json.busArray)
    }
    

    JSON每10秒下载一次,并触发 updateUI 方法,删除现有注释并添加新注释。

    如果需要的话,模型如下:

    struct MyModelClass: Codable {
        let busArray: [Bus]
    
        enum CodingKeys: String, CodingKey {
            case busArray = "result"
        }
    
        init(busArray: [Bus]) {
            self.busArray = busArray
        }
    }
    
    class Bus: NSObject, Codable, MKAnnotation {
        let latitude, longitude: Double
        let time, title, brigade: String?
        var coordinate: CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: 52.22977, longitude: 21.01178)
    
        enum CodingKeys: String, CodingKey {
            case latitude = "Lat"
            case longitude = "Lon"
            case time = "Time"
            case title = "Lines"
            case brigade = "Brigade"
        }
    
        required init(from decoder: Decoder) throws {
            let container = try decoder.container(keyedBy: CodingKeys.self)
    
            self.latitude = try container.decode(Double.self, forKey: .latitude)
            self.longitude = try container.decode(Double.self, forKey: .longitude)
            self.title = try container.decode(String.self, forKey: .title)
            self.time = try container.decode(String.self, forKey: .time)
            self.brigade = try container.decode(String.self, forKey: .brigade)
            self.coordinate = CLLocationCoordinate2D(latitude: CLLocationDegrees(latitude), longitude: CLLocationDegrees(longitude))
    
    3 回复  |  直到 6 年前
        1
  •  0
  •   OverD    6 年前

    我会在总线类中添加一个busID字段。为了将总线添加到映射中,我将创建一个方法,专门添加新的总线。您应该使用for循环(或等效的)来匹配busID并修改它的新位置。

    我希望这能把你引向正确的方向。

        2
  •  0
  •   Gerd Castan    6 年前

    像这样的?

    enter image description here

    我是靠 将annotationView作为注释添加到 MapView .

    相反,我做了一些

    mapView.addSubview(annotaionView)
    

    之后,使用iOS的一种方式来制作动画 UIViews

    最简单的方法是使用 UIView.animate{ }

    在上面的例子中,我使用 UIKit dynamics https://www.raywenderlich.com/2326-uikit-dynamics-tutorial-getting-started

    你需要的一件事,就是把地图坐标转换成 UIView

     var snapTo = mapView.convert(cdPOI.coordinate, toPointTo: mapView)
    

    动画完成后,我将注释作为子视图移除,并执行以下操作 mapView.addAnnotation(annotation)

        3
  •  0
  •   mrkot    6 年前

    下面是我根据OverD的答案写的一段代码。价值 subtitle 与busID相同。

    DispatchQueue.global().async {
    
                    for old in self.mapView.annotations {
                        for new in model.busArray {
                            if new.busID == old.subtitle {
                                if let annotation = old as? Bus {
                                    DispatchQueue.main.async {                          
                                        annotation.coordinate = new.coordinate
                                    }
                                }
                            }
                        }
                    }
    
                }
    

    编辑-重构并使annotationView从旧坐标平滑地移动到新坐标。

    func matchIDs(mapView: MKMapView, annotations: [MKAnnotation], model: MyModel) {
    
            DispatchQueue.global().async {
                for annotation in annotations {
                    if let filteredBus = model.busArray.filter({ $0.busID == annotation.subtitle }).first {
                        DispatchQueue.main.async {
    
                            UIView.animate(withDuration: 0.5, animations: {
                                let matchedBus = annotation
                                if let annotationForView = mapView.view(for: matchedBus)?.annotation as? Bus {
                                    annotationForView.coordinate = filteredBus.coordinate
                                }
                            })
    
                        }
                    } else {
                        // do nothing
                    }
                }
            }
        }
    

    我还实现了一个 viewFor annotation