Background and problem analysis
In some third-party map SDKS, there is a property called zoomLevel, which is used to set the zoomLevel of the map.
But the iOS map control MKMapView does not have such a property. Instead, MKCoordinateSpan and MKCoordinateSpan are used to configure the size of the center and area scaling displayed on the map.
MKCoordinateRegion and MKCoordinateSpan
Let’s first look at the two initialization methods for MKCoordinateRegion and MKCoordinateSpan:
MKCoordinateRegion(center: CLLocationCoordinate2D, span: MKCoordinateSpan)
MKCoordinateSpan(latitudeDelta: CLLocationDegrees, longitudeDelta: CLLocationDegrees)
Copy the code
Combined with the documents, MKCoordinateRegion can be understood as a square area on the map, center is the central geographic coordinate of the square area, and MKCoordinateSpan is the latitude and longitude range of the area, then the value range of its two parameters is:
- LatitudeDelta: [0, 180]
- longitudeDelta: [0, 360]
Tiled web map
Now that we know about MKCoordinate system and MKCoordinate Pan, how can we use them to calculate zoomLevel? Here we need to take a look at the concept of Tiled Web Map. Tiled Web Map was originally designed to better transfer and display Maps on the Web. Google Maps was first used and has gradually become an unwritten standard among mapping tools. It cuts the map into many small pieces in the form of images: tiles. When the user slides or zooms on the map, more tiles are loaded, which is more efficient and better than loading a large block of images directly.
Most Tiled Web Maps follow the implementation criteria of Google Maps:
- a
Tile
It’s 256×256 pixels. - When zoom Level is 0, the entire world map can be displayed in a single map
Tile
On. - For each additional map zoom level, one
Tile
The number of pixels will double. In other words, oneTile
Will be fourTile
Replace.
The image above is a Mosaic from Troybrant.net.
According to the above criteria, we can get the following formula:
W is the pixel length on one side of the map.
ZoomLevel algorithm parsing
We know that the earth’s longitude is 360 degrees a week, so how many pixels does a longitude range take up in a Tiled Web map? Simple division tells us:
MKCoordinateSpan is the latitude and longitude of the area that the map shows, Suppose we set the width of the MKMapView to width, and MKCoordinateSpan. LongitudeDelta is the MKMapView range of the longitude of the display area. So we can get this equation:
A simple transformation can obtain the calculation formula of zoomLevel:
The sample code
In code:
let mapWidth = mapView.frame.size.width
let zoomLevel = log2(360 * Double(mapWidth) / 256.0 / mapView.region.span.longitudeDelta)
Copy the code
We can also extend MKMapView:
extension MKMapView {
var zoomLevel: Double {
return log2(360 * Double(frame.size.width) / 256.0 / region.span.longitudeDelta)
}
}
Copy the code
The resources
- Wikipedia: Tiled Web Map
- Mapbox Medium blog: 512 map tiles
- Stackoverflow: Setting the zoom level for a MKMapView
- troybrant blog: mkmapview and zoom levels a visual guide
- Microimages: Setting Zoom Levels