我正在构建一个应用程序,我必须在世界地图上动态突出显示一些国家/地区。
总之我想自定义ios地图的整个视图,如图所示。 这可以使用 MapKit 来完成还是有其他方法。预先感谢
您想要查看 Mapbox iOS SDK,它将允许您使用类似 MapKit 的 API 来完成此操作以及更多操作。特别是,您将希望使用提供的世界国家边界自然地球数据集通过 TileMill 快速制作自定义地图,启用 UTFGrid 交互性以便可以识别点击的区域,并在
上使用
RMShape
类RMAnnotation
到地图视图上,根据需要添加/着色国家/地区多边形。这听起来有点复杂,但工具是存在的,而且是完全免费和开源的,我可以帮助您完成这个过程。
我最近研究了实现类似功能的一些可能性,现在您实际上可以非常轻松地实现类似的功能,而无需额外的库。为此,您需要国家边界坐标数据,您可以从 Natural Earth (https://www.naturalearthdata.com/) 获取该数据。不幸的是,这些数据的格式在 iOS 上无法轻松读取,但您可以使用 QGIS 将其转换为 json 格式或精确的 geojson 格式(https://www.qgis.org/en/site/forusers/download)。 html)或者您可以使用其他人转换的geojson。这是一个带有国家坐标的geojson:https://github.com/nvkelso/natural-earth-vector/blob/master/geojson/ne_110m_admin_0_countries.geojson应该满足此问题中任务的需求。
我们可以解析geojson文件并使用CAShapeLayers绘制地图。下面是一个示例代码,它使用 geojson 中的形状随机颜色绘制地图,它给了我结果,如下面的屏幕截图所示,我认为它与预期结果非常接近,因此修改它应该很容易。
Geojson解析及地图绘制代码示例:
import UIKit
import CoreLocation
struct GeoJson: Codable {
let type: String
let features: [GeoJsonFeature]
}
struct GeoJsonFeature: Codable {
let type: String
let geometry: GeoJsonGeometry
}
struct GeoJsonGeometry: Codable {
let type: String
let coordinates: GeoJsonCoordinates
}
struct GeoJsonCoordinates: Codable {
var point: [Double]?
var line: [[Double]]?
var polygon: [[[Double]]]?
var multiPolygon: [[[[Double]]]]?
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let point = try? container.decode([Double].self) {
self.point = point
return
}
if let line = try? container.decode([[Double]].self) {
self.line = line
return
}
if let polygon = try? container.decode([[[Double]]].self) {
self.polygon = polygon
return
}
if let multiPolygon = try? container.decode([[[[Double]]]].self) {
self.multiPolygon = multiPolygon
return
}
throw DecodingError.valueNotFound(Self.self, .init(codingPath: [], debugDescription: ""))
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
loadGeoJson()
}
func loadGeoJson() {
guard let url = Bundle.main.url(forResource: "ne_110m_admin_0_countries", withExtension: "geojson"),
let data = try? Data(contentsOf: url),
let geoJson = try? JSONDecoder().decode(GeoJson.self, from: data)
else {
return
}
for feature in geoJson.features {
let geometry = feature.geometry
let randomColor = UIColor(hue: Double.random(in: 0...1), saturation: 1, brightness: 1, alpha: 1)
// check https://macwright.com/2015/03/23/geojson-second-bite.html for other types info if needed
// note that below we do not support it exactly as it should (internal cutouts in polygons are ignored)
// but for needed purpose it should not make a big difference
if geometry.type == "Polygon", let coordinates = feature.geometry.coordinates.polygon {
for polygon in coordinates {
addShape(polygon: polygon, color: randomColor)
}
}
if geometry.type == "MultiPolygon", let coordinates = feature.geometry.coordinates.multiPolygon {
for multiPolygon in coordinates {
for polygon in multiPolygon {
addShape(polygon: polygon, color: randomColor)
}
}
}
}
}
func addShape(polygon: [[Double]], color: UIColor) {
let polygonCoordinates: [CLLocationCoordinate2D] = polygon.map { coordinate in
CLLocationCoordinate2D(latitude: coordinate[1], longitude: coordinate[0])
}
let points: [CGPoint] = polygonCoordinates.map { coordinate in
coordinateToPoint(coordinate)
}
let path = UIBezierPath()
path.move(to: points[0])
for point in points {
path.addLine(to: point)
}
path.close()
let shapeLayer = CAShapeLayer()
shapeLayer.path = path.cgPath
shapeLayer.fillColor = color.cgColor
shapeLayer.position = CGPoint(x: 50, y: 200)
view.layer.addSublayer(shapeLayer)
}
func coordinateToPoint(_ coordinate: CLLocationCoordinate2D) -> CGPoint {
let width = 300.0
let height = 200.0
let x = (coordinate.longitude + 180.0) * (width / 360.0)
let latitudeRadians = coordinate.latitude * .pi / 180.0
let n = log(tan((.pi / 4.0) + (latitudeRadians / 2.0)))
let y = (height / 2.0) - (width * n / (2.0 * .pi))
return CGPoint(x: x, y: y)
}
}
这是带有国家坐标的 geojson: https://github.com/nvkelso/natural-earth-vector/blob/master/geojson/ne_110m_admin_0_countries.geojson 这应该符合这个问题中任务的需要。
根据这个数据,克里米亚属于俄罗斯,这是不正确的。