您可以将图片作为图块图层添加在地图上。图块图层会放置在特定缩放级别的地图图块之上。如果您有足够的图块,则可以在多个缩放级别为整个地图补充 Google 的地图数据。
简介
借助图块图层(有时称为图块叠加层),您可以在 Google 的基本地图图块上叠加图像。这是向应用添加数据(例如地图注点或交通信息)和本地图像的绝佳方式。与 kGMSTypeNone
地图类型搭配使用时,图块图层可让您有效地将 Google 的基本地图数据替换为您自己的数据。
如果您要为地图添加大量图像(通常覆盖大片地域),就需要使用图块图层。而如果想将单个图片固定在地图上的某一点,则适合使用地面叠加层。
图块坐标
Maps API 将各缩放级别的图像分解成一组以有序网格形式排列的方形地图图块。当地图滚动至新位置,或者切换到新的缩放级别时,Maps API 会确定需要哪些图块,并将该信息转换为需要检索的一组图块。
为了便于 Google 实现墨卡托投影法,坐标为 (0,0) 的图块始终位于地图的西北角,x
值从西向东增加,y
值从北向南增加。系统使用基于该原点的 x,y
坐标为图块建立索引。例如,缩放级别为 2 时,地球分成 16 个图块,每个图块都可通过唯一的 x,y
来定位。
每个地图图块都是一个256x256的正方形点阵。缩放级别为 0 时,整个世界使用单个图块渲染。每个缩放级别都会使放大倍率增加一倍。因此,缩放级别为 1 时,地图将渲染为一个 2x2 图块网格;缩放级别为 2 时,渲染为一个 4x4 网格;缩放级别为 3 时,渲染为一个 8x8 网格,依此类推。如果您要为图块图层创建图片,则需要为您希望支持的每个缩放级别的每个图块创建一个新的 256x256 像素图片。
添加图块图层
- 实例化
GMSURLTileLayer
对象,或GMSTileLayer
或GMSSyncTileLayer
的自定义子类。 - (可选)修改
zIndex
属性,以调整其相对于其他功能块图层的位置。 - 通过设置
GMSTileLayer
对象的map
属性,将其分配给地图。
Maps SDK for iOS 提供了三个可用于实现功能块图层的类。对于每个类,您都需要定义如何为给定的一组 {x,y,zoom}
坐标提取正确的地图图块。可用的选项包括:
- 子类
GMSSyncTileLayer
,提供返回UIImage
实例的tileForX:y:zoom
实现。 - 创建
GMSTileLayer
的子类,提供异步方法requestTileForX:y:zoom
的实现,该方法稍后会使用功能块图片进行回调。 - 使用现有类
GMSURLTileLayer
自动从网址提取功能块,提供GMSTileURLConstructor
块。GMSURLTileLayer
是一个无法进行子类化的具体类。
如果对 GMSSyncTileLayer
或 GMSTileLayer
进行子类化,提供 nil
功能块结果会告知 Maps SDK for iOS 数据目前不可用,但未来可能会可用。或者,返回 kGMSTileLayerNoTile
以指示此位置没有功能块。
对于 GMSURLTileLayer
,从 GMSTileURLConstructor
返回 nil
表示此位置没有功能块。
使用GMSURLTileLayer通过网址提取图块
GMSURLTileLayer
不需要子类化,但您必须实现 GMSTileURLConstructor
代码块。以下代码展示了如何使用 GMSURLTileLayer
显示多层建筑的平面图。
Swift
let floor = 1 // Implement GMSTileURLConstructor // Returns a Tile based on the x,y,zoom coordinates, and the requested floor let urls: GMSTileURLConstructor = { (x, y, zoom) in let url = "https://www.example.com/floorplans/L\(floor)_\(zoom)_\(x)_\(y).png" return URL(string: url) } // Create the GMSTileLayer let layer = GMSURLTileLayer(urlConstructor: urls) // Display on the map at a specific zIndex layer.zIndex = 100 layer.map = mapView
Objective-C
NSInteger floor = 1; // Create the GMSTileLayer GMSURLTileLayer *layer = [GMSURLTileLayer tileLayerWithURLConstructor:^NSURL * _Nullable(NSUInteger x, NSUInteger y, NSUInteger zoom) { NSString *url = [NSString stringWithFormat:@"https://www.example.com/floorplans/L%ld_%lu_%lu_%lu.png", (long)floor, (unsigned long)zoom, (unsigned long)x, (unsigned long)y]; return [NSURL URLWithString:url]; }]; // Display on the map at a specific zIndex layer.zIndex = 100; layer.map = mapView;
通过为GMSSyncTileLayer划分子类将图块用作UIImage
GMSSyncTileLayer
和 GMSTileLayer
是可进行子类化的抽象类。您可以使用这些类以 UIImage
的形式提供功能块。以下示例展示了如何通过派生 GMSSyncTileLayer
在地图上的某些图块上渲染自定义图片。
Swift
class TestTileLayer: GMSSyncTileLayer { override func tileFor(x: UInt, y: UInt, zoom: UInt) -> UIImage? { // On every odd tile, render an image. if (x % 2 == 1) { return UIImage(named: "australia") } else { return kGMSTileLayerNoTile } } }
Objective-C
@interface TestTileLayer : GMSSyncTileLayer @end @implementation TestTileLayer - (UIImage *)tileForX:(NSUInteger)x y:(NSUInteger)y zoom:(NSUInteger)zoom { // On every odd tile, render an image. if (x % 2 == 1) { return [UIImage imageNamed:@"australia"]; } else { return kGMSTileLayerNoTile; } } @end
要将图层添加到地图,请实例化对象并设置其地图属性。
Swift
let layer = TestTileLayer() layer.map = mapView
Objective-C
GMSTileLayer *layer = [[TestTileLayer alloc] init]; layer.map = mapView;
用于Retina设备的高DPI图块
您可以将 tileSize
设置为 512,以便在 GMSSyncTileLayer
或 GMSURLTileLayer
中使用高 DPI 图片。tileSize
属性表示返回的功能块图片的首选显示像素数;默认为 256,即非 Retina 设备上 Google 地图功能块的尺寸。
如果您要在高 DPI 设备上显示正常 DPI 功能块,可以将 tileSize
设置为 512,以放大图片。请注意,放大图片可能会降低图片质量,尤其是细线或文字。为获得最佳效果,请将 tileSize
和图片 DPI 与显示屏匹配。在 Retina 设备上显示地图时,如果使用 tileSize
为 512 的高 DPI 图片,地图的显示效果会最佳;而在非 Retina 设备上显示地图时,如果使用普通图片和默认 tileSize
(256),地图的显示效果会非常出色。
清除过时图块
如果图层提供的图块变得“过时”,则应对图层调用 clearTileCache
方法以强制刷新。这会使该图层上的所有图块重新加载。
Swift
layer.clearTileCache()
Objective-C
[layer clearTileCache];