Tile Layers

選取平台: 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

您可以將 tileSize 設為 512,將高 DPI 圖片與 GMSSyncTileLayerGMSURLTileLayer 搭配使用。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];