Kick Your Ass

专业贴膜师,iOS/MacOS开发者,业余Python

一个高尚的人,一个纯粹的人,一个有道德的人,一个坚决不脱离低级趣味的人。


瓦片地图在iOS项目中的应用(一)

这次来跟大家分享一下如何使用开源地图来做地图模块放入自己的App中.
这里需要普及一些知识.

瓦片地图

简单点来讲,我们可以把一张地图看成有很多张正方形图片组成的,就像瓦片一样排放,但是这个排放是有一定的规律的.当然地图的缩放等级决定了图片的数量.

举个🌰
以世界地图为例,那么在缩放等级为0的情况下,就需要一个地图就能显示完.如果放大一个等级,在缩放等级为1的情况下,那么就需要4张图片.
那么我们假设地图缩放等级为n,那么一幅地图就需要(4^n)张图片.

下图就是当缩放等级为1时候的世界地图.

解释下上图上面的一些信息

  • 通过各个瓦片地址下载下来的图片都是256*256大小的正方形图片.
  • 箭头左边的小图片是通过它下面的地址下载下来的,箭头右边是经过拼接后组成的世界地图.
  • 下载地址中的链接可以接单做下介绍,这里我使用的是Google的瓦片地图地址.
    • 其中mt2是服务器地址,为了缓解压力Google提供了3台服务器,前缀分别为mt1,mt2,mt3
    • lyrs个人猜测是layers的缩写,就是图层的意思,更换不同的图层会获取不一样的地图.
      • lyrs = m就是常规的Google地图.
      • lyrs = s是Google的卫星图.
      • lyrs = p是Google的地形图.
    • x和y就是把地球通过墨卡托投影到平面上后的坐标.

      关于这个墨卡托投影没必要深究,大概明白是怎么回事就可以了.

    • z就是地图的缩放等级,z值越大,比例尺越大,但地图精确度越小.

瓦片地图地址

这里我简单介绍几种.

  1. OpenStreetMap
  2. OpenCycleMap
  3. Mapquest
  4. Google开源地图

    下面这些只是例子
    http://mt2.google.cn/vt/lyrs=m&hl=zh-CN&gl=cn&x=0&y=0&z=1

  5. 高德地图

    http://wprd02.is.autonavi.com/appmaptile?style=7&x=0&y=0&z=1

各个瓦片地图格式

NSString * const googleStandard = @"http://mt0.google.cn/vt/lyrs=m&hl=zh-CN&gl=cn&x={x}&y={y}&z={z}";

NSString * const googleSatellite = @"http://mt0.google.cn/vt/lyrs=s&hl=zh-CN&gl=cn&x={x}&y={y}&z={z}";

NSString * const googleTerrain = @"http://mt0.google.cn/vt/lyrs=p&hl=zh-CN&gl=cn&x={x}&y={y}&z={z}";

NSString * const opencyclemap = @"http://b.tile.opencyclemap.org/cycle/{z}/{x}/{y}.png";

NSString * const openstreetmap = @"http://tile.openstreetmap.org/{z}/{x}/{y}.png";

NSString * const landscape = @"http://a.tile.opencyclemap.org/landscape/{z}/{x}/{y}.png";

NSString * const gaodeMap = @"http://wprd02.is.autonavi.com/appmaptile?style=7&x={x}&y={y}&z={z}.png";

瓦片地图在iOS项目中使用

瓦片地图拼接完之后,是依托于MapKitmapView这个控件的,需要在mapView上添加一个图层.在MapKit中这个图层也有个类叫做MKTileOverlay.把这个图层添加到mapView中之后,通过重新渲染描绘替换掉MapKit中自带的高德地图.

下面是把OpenStreetMap添加到mapView

#import "ViewController.h"
#import <MapKit/MapKit.h>
NSString * const openstreetmap = @"http://tile.openstreetmap.org/{z}/{x}/{y}.png";

@interface ViewController ()<MKMapViewDelegate>
@property (weak, nonatomic) IBOutlet MKMapView *mapView;
@property (strong,nonatomic) MKTileOverlay *customOverlay;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.mapView.delegate = self;
    [self.mapView addOverlay:self.customOverlay];
}

- (MKTileOverlay *)customOverlay{
    if (!_customOverlay) {
        _customOverlay = [[MKTileOverlay alloc]initWithURLTemplate:openstreetmap];
        _customOverlay.canReplaceMapContent = YES;
    }
    return _customOverlay;
}
#pragma mark - MKMapViewDelegate
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay{
    if ([overlay isKindOfClass:[MKTileOverlay class]]) {
        return [[MKTileOverlayRenderer alloc]initWithTileOverlay:overlay];
    }else{
        return nil;
    }
}
@end

运行之后大致是这个样子.

至此,我们就能看到mapView中已经不是自带的高德地图了,而是OpenStreetMap.

后续会在这个基础上更新,讲一下如何自定义用户位置,运动轨迹追踪,下载瓦片地图等.

最近的文章

iOS中的定时器

认知讲到定时器,需要了解一个概念,叫做RunLoop,从字面意义上理解为运行循环.iOS里有两套API可以访问到RunLoop,NSRunLoop和CFRunLoopRef,一个来自Foundation框架,另一个来自Core Foundation.每一个线程都会对应一个RunLoop,但是RunLoop并不是随着线程的创建而生成的,实际上RunLoop也不允许被开发者创建,可以通过调用[NSRunLoop currentRunLoop];或者CFRunLoopGetCurrent();来...…

iOS继续阅读
更早的文章

UIView-Autolayout的简单使用

iPhone6和iPhone6 plus问世之后,iOS开发的屏幕适配就又稍微麻烦了一些,但是如果能熟练使用Autolayout的话,屏幕适配也不是什么难事.众所周知的Autolayout可以在storyboard里通过添加约束来实现,这样是比较简单的.如果用代码的话,是比较麻烦的,包括用VLF语言开发效率也不是很高.那么这里给大家推荐一个非常轻量级的三方框架,准确来说也不算是一个框架,它是给UIView添加一个分类,使用起来非常简单.这里先贴出github地址:https://githu...…

iOS继续阅读