首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在特定的缩放和仅接近用户放大的地方生成注释?

如何在特定的缩放和仅接近用户放大的地方生成注释?
EN

Stack Overflow用户
提问于 2022-09-03 18:35:57
回答 2查看 74关注 0票数 0

我的应用程序请求JSON数据(纬度、经度和关于一个地方的其他信息),然后以可点击注释的形式在地图上显示这些数据。我收到了大约3万份,所以正如你所能想象的,这个应用程序可能会有一点“滞后”。

我认为最适合应用程序的解决方案是,只在一定的缩放级别上显示这些注释(例如,当用户缩放时,只有一个城市一次可见,注释就会显示出来)。因为有很多,显示所有的3万可能会崩溃的应用程序,这也是为什么我也希望只显示那些接近用户放大的地方。

下面的代码立即显示所有注解同时在所有缩放级别。有没有办法让它适应到我上面描述的事情呢?

代码语言:javascript
复制
struct Map: UIViewRepresentable {
    
    @EnvironmentObject var model: ContentModel
    @ObservedObject var data = FetchData()
    
    var locations:[MKPointAnnotation] {
        
        var annotations = [MKPointAnnotation]()
        
        // Loop through all places
        for place in data.dataList {
            
            // If the place does have lat and long, create an annotation
            if let lat = place.latitude, let long = place.longitude { 
                
                // Create an annotation
                let a = MKPointAnnotation()
                a.coordinate = CLLocationCoordinate2D(latitude: Double(lat)!, longitude: Double(long)!)
                a.title = place.address ?? ""
                
                annotations.append(a)
                
            }
        }
        
        return annotations
        
    }
    
    func makeUIView(context: Context) -> MKMapView {
        
        let mapView = MKMapView()
        mapView.delegate = context.coordinator
        
        // Show user on the map
        mapView.showsUserLocation = true
        mapView.userTrackingMode = .followWithHeading
        
        return mapView
        
    }
    
    func updateUIView(_ uiView: MKMapView, context: Context) {
        
        // Remove all annotations
        uiView.removeAnnotations(uiView.annotations)
        
        // HERE'S WHERE I SHOW THE ANNOTATIONS
        uiView.showAnnotations(self.locations, animated: true)
        
    }
    
    static func dismantleUIView(_ uiView: MKMapView, coordinator: ()) {
        
        uiView.removeAnnotations(uiView.annotations)
        
    }
    
    
    // MARK: Coordinator Class
    
    func makeCoordinator() -> Coordinator {
        
        return Coordinator(map: self)
        
    }
    
    class Coordinator: NSObject, MKMapViewDelegate {
        
        var map: Map
        
        init(map: Map) {
            
            self.map = map
            
        }
        
        func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
            
            // Don't treat user as an annotation
            if annotation is MKUserLocation {

                return nil

            }
            
            // Check for reusable annotations
            var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: Constants.annotationReusedId)
            
            // If none found, create a new one
            if annotationView == nil {
                
                annotationView = MKMarkerAnnotationView(annotation: annotation, reuseIdentifier: Constants.annotationReusedId)
                
                annotationView!.canShowCallout = true
                annotationView!.rightCalloutAccessoryView = UIButton(type: .detailDisclosure)
                
            } else {
                
                // Carry on with reusable annotation
                annotationView!.annotation = annotation
                
            }
            
            return annotationView
            
        }
    }
}

寻找答案已经有一段时间了,但没有找到任何有效的答案。我想有一种方法可以让地图重新显示,然后在map中给出条件,但是不知道怎么做。谢谢你读了这么多!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-09-03 19:07:31

您的委托可以实现mapView(_:regionDidChangeAnimated:),以便在用户完成更改映射的可见区域的手势时得到通知。它可以在手势发生时实现要通知的。

您可以通过询问映射的region属性来获取它的可见区域。关于缩放级别,region文档说:

该区域包括地图中心所在的纬度和经度点,以及要显示的坐标范围。span值为映射提供隐式缩放值。显示区域越大,缩放的量就越小。同样,显示区域越小,缩放的量就越大。

updateUIView方法每次调用locations数组时都会重新计算它(因为locations是一个计算属性)。您应该检查SwiftUI调用updateUIView的频率,并决定是否需要缓存locations数组。

如果要有效地查找可见区域中的位置,请尝试将这些位置存储在四叉树中。

票数 1
EN

Stack Overflow用户

发布于 2022-11-23 19:13:23

终于发现了.

Coordinator类可以实现mapView(_:regionDidChangeAnimated:) (如@rob所说),在用户完成更改地图可见区域的手势后调用它。当发生这种情况时,将更新映射及其数组上的注释。看起来像这样..。

代码语言:javascript
复制
func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
            
   if mapView.region.span.latitudeDelta < <Double that represents zoom> && mapView.region.span.longitudeDelta < <Double that represents zoom> {
                    
        mapView.removeAnnotations(mapView.annotations)
        mapView.addAnnotations(map.getLocations(center: mapView.region.center))
                    
    }
}

..。< >中的短语( if语句中缺少的双倍)将被替换为您自己的代码(双倍越大,查看注释所需的缩放就越小)。注释数组由Map结构中定义的函数更新,如下所示.

代码语言:javascript
复制
func getLocations(center: CLLocationCoordinate2D) -> [MKPointAnnotation] {
    
    var annotations = [MKPointAnnotation]()
    let annotationSpanIndex: Double = model.latlongDelta * 10 * 0.035
    
    // Loop through all places
    for place in data.dataList {
        
        // If the place does have lat and long, create an annotation
        if let lat = place.latitude, let long = place.longitude {
            
            // Create annotations only for places within a certain region
            if Double(lat)! >= center.latitude - annotationSpanIndex && Double(lat)! <= center.latitude + annotationSpanIndex && Double(long)! >= center.longitude - annotationSpanIndex && Double(long)! <= center.longitude + annotationSpanIndex {
                
                // Create an annotation
                let a = MKPointAnnotation()
                a.coordinate = CLLocationCoordinate2D(latitude: Double(lat)!, longitude: Double(long)!)
                a.title = place.adresa ?? ""
                
                annotations.append(a)
            }
            
        }
    }
    
    return annotations
    
}

..。其中,annotationSpanIndex决定中心点周围区域的大小将显示注释(索引越大,区域越大)。理想情况下,这个区域应该略大于显示注释的缩放范围。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73594617

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档