图块图层

请选择平台: Android iOS JavaScript

您可以将图片作为图块图层添加在地图上。各图块图层以特定的缩放级别放置在一个地图图块之上。有了足够的图块,您就可以在多个缩放级别下为整个地图补充 Google 的地图数据。

简介

图块图层(有时称为图块叠加层)可让您在 Google 的基本地图图块上面叠加图像。这是向您的应用添加数据(如地图注点或交通信息)和本地图像的一种绝佳方式。当与 kGMSTypeNone 地图类型结合使用时,图块图层可以有效地让您将 Google 的基本地图数据替换成您自己的数据。

如果您想向地图添加大量图像(通常覆盖大片地域),就需要使用图块图层。而如果想将单个图片固定在地图上的某一点,则适合使用地面叠加层

图块坐标

Maps API 将各缩放级别的图像分解成一组以有序网格形式排列的方形地图图块。当地图滚动至新的位置,或者切换到新的缩放级别时,Maps API 会确定需要哪些图块,并将其转换为需要检索的一组图块。

为了便于 Google 实现墨卡托投影法,坐标为 (0,0) 的图块始终位于地图的西北角,x 值从西向东增加,y 值从北向南增加。系统使用基于该原点的 x,y 坐标为图块建立索引。例如,缩放级别为 2 时,地球分成 16 个图块,每个图块都可通过唯一的 x,y 来定位。

分为四行和四列图块的世界地图。

每个地图图块都是一个256x256的正方形点阵。缩放级别为 0 时,整个世界使用单个图块渲染。缩放级别每增加 1,放大为原来的 2 倍。因此,当缩放级别为 1 级时,地图将呈现为一个 2x2 的图块网格;当缩放级别为 2 时,是 4x4 的网格;当缩放级别为 3 时,是 8x8 的网格,依此类推。如果您正在为图块图层创建图像,则需要为您想支持的每个缩放级别下的每个图块都创建一幅 256x256 个点的新图像。

添加图块图层

  1. 实例化 GMSURLTileLayer 对象,或 GMSTileLayerGMSSyncTileLayer 的自定义子类。
  2. 可以选择修改 zIndex 属性来调整其相对于其他图块图层的位置。
  3. 通过设置 GMSTileLayer 对象的 map 属性,将其分配给地图。

Maps SDK for iOS 提供了三个可用于实现图块图层的类。对于每一个类,您都需要定义如何获取一组给定的 {x,y,zoom} 坐标所对应的正确地图图块。可用的选项包括:

  • 创建 GMSSyncTileLayer 子类,提供可返回 UIImage 实例的 tileForX:y:zoom 实现。
  • GMSTileLayer 派生出子类,并提供以后会通过图块图像进行回调的异步方法 requestTileForX:y:zoom 的实现。
  • 使用现有的类 GMSURLTileLayer 从网址自动提取功能块,并提供 GMSTileURLConstructor 代码块。GMSURLTileLayer 是无法派生子类的具体类。

在从 GMSSyncTileLayerGMSTileLayer 派生子类的情况下,提供一个 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

GMSSyncTileLayerGMSTileLayer 是用于派生出子类的抽象类。您可以通过这些类将图块用作 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,以便在 GMSSyncTileLayerGMSURLTileLayer 上使用高 DPI 图像。tileSize 属性表示返回的图块图像在显示时将优先采用的像素数量;其默认为 256,即非视网膜显示设备上 Google 地图图块的大小。

如果您要在一台高 DPI 设备上显示普通 DPI 图块,可以通过将 tileSize 设置为 512 来使图像放大。请注意,放大图片可能会降低图片质量,尤其是对于细线条或文字。为获得最佳结果,请选择与显示器相匹配的 tileSize 和图像 DPI。如果在视网膜显示设备上显示地图,当采用 512 的 tileSize 来显示高 DPI 图像时,视觉效果最好;而如果在非视网膜显示设备上显示地图,当采用默认值 256 的 tileSize 来显示普通图像时,地图看起来会很棒。

清除过时图块

如果图层提供的图块变得“过时”,那么应该对该图层调用 clearTileCache 方法以强制刷新。这会使该图层上的所有图块重新加载。

Swift

layer.clearTileCache()
      

Objective-C

[layer clearTileCache];