iOS 高德地图点聚合功能

2020-03-12  本文已影响0人  大树和小鱼

最近公司有个地图上加很多点的需求,因为web端使用了点聚合功能,业主也让我们做一个功能
这里使用了
pod 'AMap3DMap-NO-IDFA'
pod 'AMapLocation-NO-IDFA'
pod 'AMapSearch-NO-IDFA'
我们地图上的点是服务器得到的,所以其实只需要 AMap3DMap就可以了
//MARK:设置点
func setPoint(_ arr:[GYHomeTableModel]) {

    mapView.removeAnnotations(mapView.annotations)
    self.poiAnnotations.removeAll()
    var rect: MAMapRect = MAMapRectZero
    for (i,model) in arr.enumerated() {
        let poi = GYMapPOI()
        let latitude = (Double)(model.lat)
        let longitude = (Double)(model.lng)
        poi.location = AMapGeoPoint.location(withLatitude:CGFloat(latitude), longitude: CGFloat(longitude))
        
        poi.model = model
        poi.annotationTag = i + 1
        poi.pro_type = model.organ_id
        //            poi.type = model.
        if model.project_name.count > 6 {
            let str:String = String(model.project_name.prefix(6))
            poi.name = "\(str)..."
        }else {
            poi.name = model.project_name
        }
        
        self.poiAnnotations.append(poi)
        
        let annotationMapPoint = MAMapPointForCoordinate(CLLocationCoordinate2DMake(CLLocationDegrees(poi.location!.latitude), CLLocationDegrees(poi.location!.longitude)))
        ///annotation相对于中心点的对角线坐标
        let diagonalPoint = CLLocationCoordinate2DMake(mapView.centerCoordinate.latitude - (CLLocationDegrees(poi.location!.latitude) - mapView.centerCoordinate.latitude),mapView.centerCoordinate.longitude - (CLLocationDegrees(poi.location!.longitude) - mapView.centerCoordinate.longitude))
        
        let diagonalPointMapPoint = MAMapPointForCoordinate(diagonalPoint)
        
        let annotationRect = MAMapRectMake(min(annotationMapPoint.x, diagonalPointMapPoint.x), min(annotationMapPoint.y, diagonalPointMapPoint.y), abs(annotationMapPoint.x - diagonalPointMapPoint.x), abs(annotationMapPoint.y - diagonalPointMapPoint.y));
        
        rect = MAMapRectUnion(rect, annotationRect)
    }
    mapView.setVisibleMapRect(rect, edgePadding: UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5), animated: true)
    
    
    synchronized(lock: self) { [weak self] in
        
        self?.shouldRegionChangeReCalculate = false
        
        self?.mapView.removeAnnotations(self?.mapView.annotations)
        
        DispatchQueue.global(qos: .default).async(execute: { [weak self] in
            
            self?.coordinateQuadTree.build(withPOIs: self?.poiAnnotations)
            self?.shouldRegionChangeReCalculate = true
            //                DispatchQueue.main.async(execute: {
            //                    self?.addAnnotations(toMapView: (self?.mapView)!)
            //                })
        })
    }

}

这里是服务器拿到数据 并把服务器数据格式转化成AMapPOI格式 我这里是写了一个继承AMapPOI的model。用它来接受来自服务器的数据,

func addAnnotations(toMapView mapView: MAMapView) {
synchronized(lock: self) { [weak self] in

        guard (self?.coordinateQuadTree.root != nil) || self?.shouldRegionChangeReCalculate != false else {
            NSLog("tree is not ready.")
            return
        }
        
        guard let aMapView = self?.mapView else {
            return
        }
        
        let visibleRect = aMapView.visibleMapRect
        let zoomScale = Double(aMapView.bounds.size.width) / visibleRect.size.width
        let zoomLevel = Double(aMapView.zoomLevel)
        
        DispatchQueue.global(qos: .default).async(execute: { [weak self] in
            
            let annotations = self?.coordinateQuadTree.clusteredAnnotations(within: visibleRect, withZoomScale: zoomScale, andZoomLevel: zoomLevel)
            
            self?.updateMapViewAnnotations(annotations: annotations as! Array<<span style="color: #d0a8ff">ClusterAnnotation>)
        })
    }
}

func synchronized(lock: AnyObject, closure: () -> ()) {
    objc_sync_enter(lock)
    closure()
    objc_sync_exit(lock)
}
//MARK: - MAMapViewDelegate

func mapView(_ mapView: MAMapView!, didSelect view: MAAnnotationView!) {
    mapView.deselectAnnotation(view.annotation, animated: true)
    if let annotation = view.annotation as? ClusterAnnotation {
        
        if annotation.pois.count > 1 {
            var rect: MAMapRect = MAMapRectZero
            for item in annotation.pois {
                if let poi = item as? GYMapPOI {
                    let annotationMapPoint = MAMapPointForCoordinate(CLLocationCoordinate2DMake(CLLocationDegrees(poi.location!.latitude), CLLocationDegrees(poi.location!.longitude)))
                    ///annotation相对于中心点的对角线坐标
                    let diagonalPoint = CLLocationCoordinate2DMake(annotation.coordinate.latitude - (CLLocationDegrees(poi.location.latitude) - annotation.coordinate.latitude),annotation.coordinate.longitude - (CLLocationDegrees(poi.location.longitude) - annotation.coordinate.longitude))
                    
                    let diagonalPointMapPoint = MAMapPointForCoordinate(diagonalPoint)
                    
                    let annotationRect = MAMapRectMake(min(annotationMapPoint.x, diagonalPointMapPoint.x), min(annotationMapPoint.y, diagonalPointMapPoint.y), abs(annotationMapPoint.x - diagonalPointMapPoint.x), abs(annotationMapPoint.y - diagonalPointMapPoint.y));
                    
                    rect = MAMapRectUnion(rect, annotationRect)
                }
                
            }
            if !MAMapRectIsEmpty(rect) {
                mapView.setVisibleMapRect(rect, edgePadding: UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5), animated: true)
            }
        }
        
    } else if let ann = view.annotation as? GYCustomPointAnnotation {
        
        
        guard let annView = view as? GYCustomAnnotationView else{return}
        if lastAnnotation != nil {
            
            lastAnnotation?.isSelected = false
            for item in unitAnnotations {
                if item.annotationTag == lastAnnotation!.annotationTag {
                    item.isSelected = lastAnnotation!.isSelected
                    let info = getNameAndStr(item)
                    let annView = mapView.view(for: item) as! GYCustomAnnotationView
                    annView.image = UIImage.map(info.0, text: info.1, isSelected: item.isSelected)
                    break
                }
            }
            
        }
        let annInfo = getNameAndStr(ann)
        ann.isSelected = true
        annView.image = UIImage.map(annInfo.0, text: annInfo.1, isSelected: ann.isSelected)
        //            lastAnnoView = annView
        lastAnnotation = ann
        
        if ann.isSelected {//是否选中
            infoView?.tableAndDetailView?.showDetail()
            infoView?.tableAndDetailView?.DetailData(ann.model)
            infoView?.tableAndDetailView?.titleLabel.text = ann.model.project_name;
            popView?.toCenter();
        }else {
            infoView?.tableAndDetailView?.showTable()
        }
    }
    
}



func mapView(_ mapView: MAMapView!, viewFor annotation: MAAnnotation!) -> MAAnnotationView! {
    if annotation is ClusterAnnotation {
        let annotation = annotation as! ClusterAnnotation
        let pointReuseIndetifier = "pointReuseIndetifier"
        
        var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: pointReuseIndetifier) as? ClusterAnnotationView
        
        if annotationView == nil {
            annotationView = ClusterAnnotationView(annotation: annotation, reuseIdentifier: pointReuseIndetifier)
        }
        
        annotationView?.annotation = annotation
        annotationView?.count = UInt((annotation ).count)
        switch type {
        case 1:
            annotationView?.backColor = UIColor.init(named: "DarkOrangeColor")
        case 2:
            annotationView?.backColor = UIColor.init(named: "OrangeColor")
        case 3:
            annotationView?.backColor = UIColor.init(named: "RedColor")
        case 4:
            annotationView?.backColor = UIColor.init(named: "MainColor")
        case 5:
            annotationView?.backColor = UIColor.init(named: "GreenColor")
        default:
            break
            
        }
        
        
        return annotationView
    }
    
    if annotation is GYCustomPointAnnotation {
        let anno = annotation as! GYCustomPointAnnotation
        var annView = mapView.dequeueReusableAnnotationView(withIdentifier: "annotationResuseIndetifier")
        //                   var annView = mapView.dequeueReusableAnnotationView(withIdentifier: "annotationResuseIndetifier")as? GYCustomAnnotationView
        if annView == nil {
            annView = GYCustomAnnotationView(annotation: anno, reuseIdentifier: "annotationResuseIndetifier")
        }
        annView?.tag = anno.annotationTag
        annView?.canShowCallout = false
        annView?.isDraggable = false
        var imageStr = ""
        
        if anno.type == 1 {//广州冠粤
            imageStr = ""
        }else if (anno.type == 2){//路基桥涵(工程一部)
            imageStr = "pop_map_yellow"
        }else if (anno.type == 3){//路面工程(工程二部)
            imageStr = "pop_map_red"
        }else if (anno.type == 4) {//地方项目(工程三部)
            imageStr = "pop_map_blue"
        }else if (anno.type == 5) {//养护项目
            imageStr = "pop_map_green"
        }
        
        
        annView?.image = UIImage.map(imageStr, text: anno.contentStr as NSString, isSelected: anno.isSelected)
        //设置偏移量,使其旗子正好插在位置
        annView?.centerOffset = CGPoint(x: annView!.image.size.width/2, y: -annView!.image.size.height/2)
        return annView
    }
    
    return nil
}

func mapView(_ mapView: MAMapView!, didDeselect view: MAAnnotationView!) {
    //        customCalloutView.dismiss()
    //        customCalloutView.delegate = nil
}



func mapView(_ mapView: MAMapView!, regionDidChangeAnimated animated: Bool) {
    print("zoomLevel",mapView.zoomLevel)
    
    let visibleRect = mapView.visibleMapRect
    let zoomScale = Double(mapView.bounds.size.width) / visibleRect.size.width
    let zoomLevel = Double(mapView.zoomLevel)
    if let annotations = self.coordinateQuadTree.clusteredAnnotations(within: visibleRect, withZoomScale: zoomScale, andZoomLevel: zoomLevel) as? [ClusterAnnotation] {
        
        mapView.removeAnnotations(unitAnnotations)
        unitAnnotations.removeAll()
        var newAnnotations = [ClusterAnnotation]()
        
        for index in (0..
            let annotation = annotations[index]
            if annotation.pois.count > 1 {
                //                    annotation.type =
                newAnnotations.append(annotation)
                
            } else {
                for item in annotation.pois {
                    if let poi = item as? GYMapPOI {
                        let ann = GYCustomPointAnnotation()
                        ann.annotationTag = poi.annotationTag
                        ann.type = poi.pro_type
                        ann.coordinate = CLLocationCoordinate2DMake(CLLocationDegrees(poi.location!.latitude), CLLocationDegrees(poi.location!.longitude))
                        ann.contentStr = poi.name
                        ann.model = poi.model
                        if lastAnnotation != nil {
                            if lastAnnotation?.annotationTag == ann.annotationTag {
                                ann.isSelected = lastAnnotation!.isSelected
                            }else {
                                ann.isSelected = false
                            }
                        }
                        
                        
                        unitAnnotations.append(ann)
                    }
                    
                }
            }
            
        }
        mapView.addAnnotations(unitAnnotations)
        
        updateMapViewAnnotations(annotations: newAnnotations)
        
    }
}

这里主要还是在移动屏幕以后,找到最后点击的view ,这边是把它先存起来,用的时候在数组里面遍历一次,通过tag寻找他 ,改变他的选中状态。 还有就是 点击聚合 展示这个聚合所有的点。需要在didSelect方法里面判断是点击的聚合还是view。聚合的话,获取聚合里面所有的点,把这些点坐标转换一下,展示在地图里面
还有一些关键的类,是直接用的官方demo的代码,我就懒得copy了,。贴一下他们的地址 https://lbs.amap.com/dev/demo/cluster-marker#iOS
https://github.com/amap-demo/iOS-cluster-marker
吐槽一下,他们的代码还需要自己pod install 一下,不然不能运行

非常感谢我们组长 最关键的大部分都是他帮助我写的,所以今天买了老干妈请他吃

上一篇下一篇

猜你喜欢

热点阅读