美文网首页
iOS 高德地图点聚合功能

iOS 高德地图点聚合功能

作者: 大树和小鱼 | 来源:发表于2020-03-12 15:23 被阅读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 一下,不然不能运行

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

    相关文章

      网友评论

          本文标题:iOS 高德地图点聚合功能

          本文链接:https://www.haomeiwen.com/subject/ctkpjhtx.html