計算MKMapView的zoomLevel(地圖縮放等級)
在一些第三方的地圖 SDK 中,往往會有 zoomLevel
這樣一個屬性,常用於設定地圖的縮放等級。
但是在 iOS 自帶的地圖控制元件 MKMapView
是沒有這樣一個屬性的。取而代之的是利用 MKCoordinateRegion
和 MKCoordinateSpan
來配置地圖顯示的中心和區域縮放的大小。
MKCoordinateRegion 和 MKCoordinateSpan
我們先來看看 MKCoordinateRegion
和 MKCoordinateSpan
的這兩個初始化方法:
MKCoordinateRegion(center: CLLocationCoordinate2D, span: MKCoordinateSpan) MKCoordinateSpan(latitudeDelta: CLLocationDegrees, longitudeDelta: CLLocationDegrees) 複製程式碼
結合文件 ,我們可以將 MKCoordinateRegion
理解為地圖上一塊方形區域, center
是這塊方形區域的中心地理座標,而 MKCoordinateSpan
是這塊區域的 經緯度範圍 ,那麼它的兩個引數的取值範圍是:
- latitudeDelta:[0, 180]
- longitudeDelta: [0, 360]

Tiled web map
瞭解了 MKCoordinateRegion
和 MKCoordinateSpan
後,我們該如何利用它們來計算出 zoomLevel
呢?這裡我們需要先了解一下Tiled web map 這個概念。 Tiled web map
的設計初衷是為了能在網路上更好的傳輸和展示地圖,其中最早應用起來的是 Google Maps
, 然後慢慢地成為了地圖工具中一個不成文的標準。它把地圖以圖片的形式切割成很多個小塊: Tile
,當用戶在地圖上滑動或者縮放時,就會載入更多的 Tile
,對比以前直接載入一大塊圖片的方式效率更高,使用者體驗更好。
大部分的 Tiled web map
會依據 Google Maps 的一些實現標準:
- 一個
Tile
是 256x256 畫素。 - zoom Level 為 0 時,整個世界地圖可以顯示在單個
Tile
上。 - 每增加一個地圖縮放等級,一個
Tile
的畫素會加倍。也就是說一個Tile
會被四個Tile
替換掉。

上面原圖片來自troybrant.net,由原圖拼接而成。
根據上面的標準,我們可以得出這樣一個公式:
W 表示地圖一邊長的畫素。
zoomLevel 演算法解析
我們知道地球經度一週360度,那麼一個經度範圍佔 Tiled web map
的多少畫素呢?簡單的除法可以得知:
上面說到 MKCoordinateSpan
它表示地圖顯示區域的 經緯度範圍 ,假設我們把 MKMapView
的寬度設定為 width
, 而 MKCoordinateSpan.longitudeDelta
是當前 MKMapView
顯示區域的 經度 範圍。那麼我們可以得到這樣一個等式:
一個簡單的轉換,即可得出 zoomLevel
的計算公式:
示例程式碼
用程式碼形式展示:
let mapWidth = mapView.frame.size.width let zoomLevel = log2(360 * Double(mapWidth) / 256.0 / mapView.region.span.longitudeDelta) 複製程式碼
我們還可以給 MKMapView
擴充套件一下:
extension MKMapView { var zoomLevel: Double { return log2(360 * Double(frame.size.width) / 256.0 / region.span.longitudeDelta) } } 複製程式碼