You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS16 SwiftUI中如何判断地图可视区域是否包含标注

解决方案:SwiftUI iOS16地图可视区域标注检测与列表展示

1. 定义标注数据结构

先实现符合SwiftUI地图要求的标注模型,需遵循Identifiable和MKAnnotation协议:

import MapKit

struct LocationAnnotation: Identifiable, MKAnnotation {
    let id = UUID()
    var coordinate: CLLocationCoordinate2D
    var title: String?
    var subtitle: String?
}

2. 核心逻辑:检测可视区域内的标注

通过ViewModel监听地图相机位置变化,实时过滤出当前可视范围内的标注:

import SwiftUI
import MapKit

class MapViewModel: ObservableObject {
    // 全部标注数据
    @Published var allAnnotations: [LocationAnnotation] = []
    // 当前可视区域内的标注
    @Published var visibleAnnotations: [LocationAnnotation] = []
    // 地图相机位置,用于监听视角变化
    @Published var cameraPosition: MapCameraPosition = .automatic
    
    init() {
        // 模拟初始化标注数据
        let sampleAnnotations = [
            LocationAnnotation(coordinate: CLLocationCoordinate2D(latitude: 39.9042, longitude: 116.4074), title: "北京", subtitle: "中国首都"),
            LocationAnnotation(coordinate: CLLocationCoordinate2D(latitude: 31.2304, longitude: 121.4737), title: "上海", subtitle: "经济中心"),
            LocationAnnotation(coordinate: CLLocationCoordinate2D(latitude: 23.1291, longitude: 113.2644), title: "广州", subtitle: "南方门户")
        ]
        self.allAnnotations = sampleAnnotations
    }
    
    // 更新可视区域标注列表
    func updateVisibleAnnotations() {
        guard let currentRegion = cameraPosition.region else { return }
        let mapBounds = MKMapRect(region: currentRegion)
        
        visibleAnnotations = allAnnotations.filter { annotation in
            let annotationPoint = MKMapPoint(annotation.coordinate)
            return mapBounds.contains(annotationPoint)
        }
    }
}

3. SwiftUI视图实现

绑定相机位置,监听视角变化触发更新,根据可视标注数量动态显示/隐藏底部列表:

struct MapView: View {
    @StateObject private var viewModel = MapViewModel()
    
    var body: some View {
        ZStack(alignment: .bottom) {
            Map(position: $viewModel.cameraPosition, annotationItems: viewModel.allAnnotations) { annotation in
                MapPin(coordinate: annotation.coordinate)
                MapAnnotation(coordinate: annotation.coordinate) {
                    Text(annotation.title ?? "")
                        .font(.caption)
                        .background(.white)
                        .padding(2)
                        .cornerRadius(4)
                }
            }
            .onChange(of: viewModel.cameraPosition) { _ in
                viewModel.updateVisibleAnnotations()
            }
            
            // 底部标注列表:仅当有可视标注时显示
            if !viewModel.visibleAnnotations.isEmpty {
                VStack {
                    Divider()
                    ScrollView(.horizontal, showsIndicators: false) {
                        HStack(spacing: 16) {
                            ForEach(viewModel.visibleAnnotations) { annotation in
                                VStack(alignment: .leading) {
                                    Text(annotation.title ?? "")
                                        .font(.headline)
                                    Text(annotation.subtitle ?? "")
                                        .font(.caption)
                                        .foregroundColor(.gray)
                                }
                                .padding(12)
                                .background(.white)
                                .cornerRadius(8)
                                .shadow(radius: 2)
                            }
                        }
                        .padding(.horizontal)
                    }
                    .frame(height: 100)
                }
                .transition(.move(edge: .bottom))
                .animation(.easeInOut, value: viewModel.visibleAnnotations)
            }
        }
    }
}

关键说明

  • MapCameraPosition.region:iOS16中MapCameraPosition原生提供region属性,可直接获取当前地图可视区域范围。
  • MKMapRect.contains(_:):将标注坐标转换为MKMapPoint后,判断是否落在可视区域的矩形范围内。
  • 过渡动画:给底部列表添加边缘移动过渡,让显示/隐藏操作更流畅自然。

内容的提问来源于stack exchange,提问作者Alberto Fernandez-Baillo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 17:42:16