Mapbox 离线地图使用介绍

1. 前言

Mapbox 是一个面向开发者的地图平台。它提供易于使用、功能强大的 API,支持 iOS、Android 和 Web 等平台。具体介绍可以到 Mapbox 的 官网 查看。

本文主要以 iOS 平台为例,针对 Mapbox 提供的离线地图功能来介绍。关于前期的如何接入 Mapbox 以及其它功能的说明,请移步到 Mapbox-iOS-SDK 文档 查看。

2. Mapbox 离线地图

2.1 下载地图

2.1.1 准备地图

在下载地图前,我们应该建立了地图实例 MGLMapView 并且做好必要的配置:

let url = URL(string: "mapbox://styles/mapbox/streets-v10")
let sampleLoaction = CLLocationCoordinate2D(latitude:  22.54, longitude: 113.93)

var mapView = MGLMapView(frame: view.bounds, styleURL: url)
mapView.setCenter(sampleLoaction, zoomLevel: 16, animated: false)

2.1.2 确定下载区域

利用 MGLTilePyramidOfflineRegion 对象来确定需要下载的区域。初始化 MGLTilePyramidOfflineRegion 对象需要以下参数:

  • styleURL:地图的样式URL
  • bounds:地理区域 MGLCoordinateBounds
  • minimumZoomLevel:最小的地图层级
  • maximumZoomLevel:最大的地图层级
let region = MGLTilePyramidOfflineRegion(
        styleURL: mapView.styleURL, 
        bounds: mapView.visibleCoordinateBounds, 
        fromZoomLevel: mapView.zoomLevel, 
        toZoomLevel: 16)

2.1.3 开始下载

在 Mapbox 中,一块区域的离线地图抽象为 MGLOfflinePack 对象,利用 MGLOfflineStorage 单例创建一个 MGLOfflinePack 的方法来达到下载地图的目的。该方法还接收一个附加信息的 Data 实例,我们可以利用它来给每一块我们下载的地图附带上必要的信息,比如标记这块离线地图的名字等。

do {
    // 附加信息:这块离线地图的名字
    let userInfo = ["name": "My Offline Pack"]
    let context = try NSKeyedArchiver.archivedData(withRootObject: userInfo, requiringSecureCoding: false)

    // 传入下载区域,即上一步创建的 MGLTilePyramidOfflineRegion 实例,以及附加信息
    MGLOfflineStorage.shared.addPack(for: region, withContext: context) { (pack, error) in
        guard error == nil else { return }
        // 开始下载
        pack!.resume()
    }
} catch let error {
    print("Error: \(error.localizedDescription)")
}

2.1.4 监听下载状态

有些情况下,我们需要在前台展示离线地图的下载进度,所以我们需要知道地图下载的状态,这时候我们需要监听 Mapbox 提供的几个通知:

  • 下载进度的变化:MGLOfflinePackProgressChanged
  • 下载发生错误:MGLOfflinePackError
  • 下载达到最大限额:MGLOfflinePackMaximumMapboxTilesReached
NotificationCenter.default.addObserver(self, selector: #selector(offlinePackProgressDidChange), name: .MGLOfflinePackProgressChanged, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(offlinePackDidReceiveError), name: .MGLOfflinePackError, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(offlinePackDidReceiveMaximumAllowedMapboxTiles), name: .MGLOfflinePackMaximumMapboxTilesReached, object: nil)

2.2 查看和管理离线地图

离线地图是由 MGLOfflineStorage 这个单例来管理的。

  • 查看

通过 MGLOfflineStorage.shared.packs 获得所有离线地图的一个数组。如上面所说的,一块区域的离线地图抽象为 MGLOfflinePack 对象,所以这是一个 MGLOfflinePack 对象的数组。

通过 MGLOfflinePack 对象,我们可以获得当初下载这块地图的区域信息, 通过该区域信息,我们可以在需要查看离线地图的时候,将地图显示的区域移动到该区域:

let offlineRegion = MGLOfflineStorage.shared.packs?[0].region as? MGLTilePyramidOfflineRegion

mapView.styleURL = offlineRegion.styleURL
mapView.setVisibleCoordinateBounds(offlineRegion.bounds, animated: false)
mapView.setZoomLevel(offlineRegion.minimumZoomLevel, animated: true)
  • 移除

移除一块离线地图则可以用 removePack 的方法,它接收一个 MGLOfflinePack 的参数。

let pack: MGLOfflinePack = ...
MGLOfflineStorage.shared.removePack(pack) { (error) in
    print(error)
}
  • 更新 当有网络连接的情况下,Mapbox 会周期性的请求网络来重新验证缓存的地图信息,如果有新的地图信息,会更新这部分缓存的地图信息。

3. Mapbox 离线地图限额与定价

Mapbox 下载离线地图是有一定的限额的,如果默认提供的限额达不到你的业务需求,可以通过加入 enterprise plan 来提升限额。

  • 计量单位 Tile Mapbox 离线地图下载量是以 Tile 作为计量单位的。
  • 最大限额 Mapbox 默认最大的限额为 6000 tiles
  • 计算方式 这个限额的计算方式并不仅仅是以区域计算,还以地图的展示样式计算,比如我们下载一块区域的地图,它有 10 个 tile,但是同时我们还下载了这个区域的卫星地图和街道地图,那么这里 Mapbox 是算你 10 x 2 = 20 个 Tile。 一个区域地图的 Tile 数目,会根据所选择的 zoom level 范围而不同。比如 6000个Tile 大约是 伦敦M25环线公路所包围的区域(zoom level 范围0–15),又或者是美国本土区域(zoom levels 范围0–9)。zoom level 范围越大,代表地图能缩放的范围越大,细节也就越多。最大的 zoom level 是25.5,而 MGLMapView 对象默认设置最大为22。 这里圈了一下 伦敦M25环线公路 所包围的区域,给大家做个参考:

Screen Shot 2018-11-03 at 23.09.42.png | center | 421x375.28054298642536

Mapbox 还提供了一个计算工具给我们: offline-estimator,你可以在地图上圈一块区域,并且设置 zoom level 范围,它就可以计算出 Tile 的数目:

Screen Shot 2018-11-03 at 23.26.37.png | center | 650x364.1035856573705

  • 价格 Mapbox 提供了三种收费计划:
    • Pay-as-you-go: 比如每个月基础 50,000 active users是免费的,超过 50,000后,以每 500 个收 0.5美元 的价格计算。
    • Commercial: 这个则在 Pay-as-you-go 的基础上,再加499美元一个月,可以享受更多的特权。
    • Enterprise: 如果上面的计划都不能满足你,那么则需要 联系他们

注意:Pay-as-you-go 和 Commercial 这两种计划所提供的都是 6000 Tile 的限额(如果处于Pay-as-you-go计划的免费状态,也是有6000tile的限额),要想进一步提升限额,则需要加入 Enterprise 计划,来进行具体沟通。

© 著作权归作者所有
这个作品真棒,我要支持一下!
奇志技术团队博客 http://meshtech.co/
0条评论
top Created with Sketch.