表示中のマップ(MKMapView)領域内に含まれている座標かどうかを判定する
検証環境:
Xcode 12
Swift 5.3
まずMapKit
をインポートしておく。
import MapKit
MKMapRect を使う
ある座標が表示中のマップMKMapView
領域内に含まれているかで判定する方法。
座標の緯度経度はCLLocationCoordinate2D
で扱っているとする。
- 表示中のマップ領域の矩形
MKMapRect
をmapView.visibleMapRect
で取得する。 - 緯度経度
CLLocationCoordinate2D
をマップ座標系MKMapPoint
に変換する。 MKMapRect#contains(_ point: MKMapPoint)
メソッドで領域内の点であるかを判定する。
let mapRect = mapView.visibleMapRect let mapPoint = MKMapPoint(coordinate) if mapRect.contains(mapPoint) { // 領域内に含まれる }
使用例: 表示中のマップ領域内に含まれるアノテーションのみ抽出する
let mapRect: MKMapRect = mapView.visibleMapRect for annotation in mapView.annotations { let mapPoint = MKMapPoint(annotation.coordinate) if mapRect.contains(mapPoint) { // 領域内に含まれる } }
MKCoordinateRegion を使う
ある座標がMKCoordinateRegion
領域内に含まれているかで判定する方法。
func standardAngle(_ angle: CLLocationDegrees) -> CLLocationDegrees { let angle = angle.truncatingRemainder(dividingBy: 360) return angle < -180 ? -360 - angle : angle > 180 ? 360 - angle : angle } func regionContains(region: MKCoordinateRegion, location: CLLocationCoordinate2D) -> Bool { let deltaLat = abs(standardAngle(region.center.latitude - location.latitude)) let deltaLon = abs(standardAngle(region.center.longitude - location.longitude)) return region.span.latitudeDelta / 2 >= deltaLat && region.span.longitudeDelta / 2 >= deltaLon }
使用例: 表示中のマップ領域内に含まれるアノテーションのみ抽出する
let region: MKCoordinateRegion = mapView.region for annotation in mapView.annotations { if regionContains(region: region, location: annotation.coordinate) { // 領域内に含まれる } }
MKCoordinateRegion の Extension にした場合。
extension MKCoordinateRegion { func contains(location: CLLocationCoordinate2D) -> Bool { let deltaLat = abs(standardAngle(center.latitude - location.latitude)) let deltaLon = abs(standardAngle(center.longitude - location.longitude)) return span.latitudeDelta / 2 >= deltaLat && span.longitudeDelta / 2 >= deltaLon } private func standardAngle(_ angle: CLLocationDegrees) -> CLLocationDegrees { let angle = angle.truncatingRemainder(dividingBy: 360) return angle < -180 ? -360 - angle : angle > 180 ? 360 - angle : angle } }
if mapView.region.contains(location: coordinate) { // 領域内に含まれる }