圖塊圖層

選取平台: Android iOS JavaScript

You can add images on top of your map as a Tile Layer. 圖塊圖層會固定在特定縮放等級下的地圖圖塊上方。有了充足的圖塊,您就能為整個地圖提供多個縮放等級的 Google 地圖資料。

簡介

圖塊圖層 (有時稱為「圖塊疊加層」) 可讓您在 Google 基本地圖圖塊上方疊加圖片。這是在應用程式中新增資料 (例如搜尋點或路況資訊) 和本機圖像的絕佳方式。搭配 kGMSTypeNone 地圖類型使用圖塊時,您可以有效將 Google 的基本地圖資料替換成自己的資料。

如果您想在地圖中加入豐富的圖像 (通常是涵蓋大型地理區域),圖塊圖層就很實用。相反地,如果您想修正地圖上的單一圖片,區域疊加層就相當實用。

圖塊座標

Maps API 會將各縮放等級的圖像,分解成一組依照順序排列的方形圖塊。地圖捲動至新位置或新的縮放等級時,Maps API 會判斷需要哪些圖塊,然後將其轉換成一組要擷取的圖塊。

在 Google 的麥卡托投影實作中,含有座標 (0,0) 的圖塊一律位於地圖的西北角,同時 x 值會從西到東逐漸增加,y 值則從北到南逐漸增加。圖塊是使用從該原點開始的 x,y 座標來建立索引。舉例來說,縮放等級為 2 時,如果將地球區分成 16 個圖塊,每個圖塊都可使用不重複的 x,y 組合參照:

由四列和四欄圖塊組成的世界地圖。

Each map tile is a 256x256 point square. 縮放等級為 0 時,整個世界都會以單一圖塊轉譯。每個縮放等級會將放大倍率加倍。因此,縮放等級為 1 時,地圖算繪為 2x2 的圖塊,或縮放等級為 2 的 4x4 格線,縮放等級為 3 等等 8x8 格線,依此類推。如果要建立圖塊圖層的圖片,您必須針對要支援的每種縮放等級建立新的 256x256 點圖片。

新增圖塊圖層

  1. GMSURLTileLayer 物件或 GMSTileLayer/GMSSyncTileLayer 的自訂子類別執行個體化。
  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
      

To add the layer to your map, instantiate the object and set its map property.

Swift

let layer = TestTileLayer()
layer.map = mapView
      

Objective-C

GMSTileLayer *layer = [[TestTileLayer alloc] init];
layer.map = mapView;
      

High DPI Tiles for Retina devices

只要將 GMSSyncTileLayerGMSURLTileLayer 設為 tileSize 至 512,即可使用高 DPI 圖片。 tileSize 屬性表示傳回的圖塊圖片顯示的像素數量;預設為 256,也就是 Google 地圖圖塊在非 Retina 裝置上的尺寸。

如果在高 DPI 裝置上顯示一般 DPI 圖塊,您可以將 tileSize 設為 512,將圖片放大。請注意,放大圖片可能會降低圖片品質,特別是在細線或文字中。為求最佳效果,請比對 tileSize 和圖片 DPI。在 Retina 裝置上顯示的地圖在顯示 tileSize 512 的高 DPI 圖像時,會呈現最佳視覺效果;而在 Retina 裝置上顯示的地圖在一般圖像和 tileSize 的 256 預設圖像上都沒有問題。

清除過時的資訊方塊

如果圖層提供的圖塊已過時,則必須對圖層呼叫 clearTileCache 方法,以強制重新整理。這項操作會重新載入這個圖層中的所有圖塊。

Swift

layer.clearTileCache()
      

Objective-C

[layer clearTileCache];