Camadas de blocos

Selecione a plataforma: Android iOS JavaScript

É possível adicionar imagens sobre o mapa como uma camada de blocos. Essas camadas são colocadas sobre um bloco de mapa em um nível de zoom específico. Com blocos suficientes, é possível complementar os dados do mapa do Google para o mapa inteiro, em vários níveis de zoom.

Introdução

As camadas de blocos (às vezes chamadas de sobreposições de blocos) permitem sobrepor imagens aos blocos do mapa básico do Google. Essa é uma excelente forma de adicionar dados, como pontos de interesse ou informações de trânsito, e imagens locais ao seu app. Quando combinadas com o tipo de mapa kGMSTypeNone, as camadas de blocos permitem substituir os dados do Mapa básico do Google pelos seus próprios.

As camadas de blocos são úteis para adicionar ao mapa várias imagens, geralmente cobrindo grandes áreas geográficas. As sobreposições de solo, por outro lado, são úteis quando você quer corrigir uma única imagem em um ponto do mapa.

Coordenadas de bloco

A API Maps divide as imagens de cada nível de zoom em um conjunto de blocos de mapa quadrados, organizados em uma grade ordenada. Quando a rolagem é mostrada no mapa para um novo local ou nível de zoom, a API Maps determina quais blocos são necessários e converte isso em um conjunto de blocos a recuperar.

Para a projeção de Mercator do Google, o bloco com a coordenada (0,0) fica sempre no canto noroeste do mapa, com valores x aumentando de oeste para leste e valores y aumentando de norte para sul. Os blocos são indexados usando coordenadas x,y dessa origem. Por exemplo, no nível de zoom 2, quando a Terra está dividida em 16 blocos, cada bloco pode ser referenciado por um par de x,y exclusivo:

Mapa do mundo dividido em 4 linhas e 4 colunas de blocos.

Cada bloco de mapa é um quadrado de 256x256 pontos. No nível de zoom 0, o mundo inteiro é renderizado em um único bloco. Cada nível de zoom aumenta a ampliação por um fator de dois. Portanto, no nível de zoom 1, o mapa é renderizado como uma grade de blocos de 2x2 ou uma grade 4x4 no nível de zoom 2, uma grade 8x8 no nível de zoom 3 e assim por diante. Se estiver criando imagens para uma camada de blocos, você precisará gerar uma nova imagem de 256 x 256 pontos para cada bloco em todos os níveis de zoom que pretende oferecer.

Adicionar uma camada de blocos

  1. Instancie um objeto GMSURLTileLayer ou uma subclasse personalizada de GMSTileLayer/GMSSyncTileLayer.
  2. Se quiser, modifique a propriedade zIndex para ajustar a posição dela em relação a outras camadas de blocos.
  3. Atribua o objeto GMSTileLayer ao mapa definindo a propriedade map.

O SDK do Maps para iOS oferece três classes que podem ser usadas para implementar uma camada de blocos. Em cada classe, você precisa definir como buscar o bloco do mapa correto para um determinado conjunto de coordenadas {x,y,zoom}. As opções disponíveis são estas:

  • Subclasse GMSSyncTileLayer, fornecendo a implementação de tileForX:y:zoom que retorna instâncias de UIImage.
  • Subclasse GMSTileLayer, fornecendo a implementação do método assíncrono requestTileForX:y:zoom, que posteriormente chamará de volta com uma imagem de bloco.
  • Use a classe existente, GMSURLTileLayer, para buscar blocos automaticamente em URLs, fornecendo o bloco GMSTileURLConstructor. GMSURLTileLayer é uma classe concreta que não pode ser subclassificada.

No caso da subclasse GMSSyncTileLayer ou GMSTileLayer, o resultado do bloco nil informa ao SDK do Maps para iOS que os dados estão indisponíveis no momento, mas podem ser disponibilizados no futuro. Você também pode retornar kGMSTileLayerNoTile para indicar que não há blocos nesse local.

Para GMSURLTileLayer, o retorno de nil do GMSTileURLConstructor vai indicar que não há um bloco nesse local.

Usar "GMSURLTileLayer" para buscar blocos de URLs

O GMSURLTileLayer não requer subclasses, mas é necessário implementar o bloco GMSTileURLConstructor. O código abaixo mostra como usar GMSURLTileLayer para mostrar a planta baixa de um edifício de vários andares.

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;
      

Crie uma subclasse GMSSyncTileLayer para servir de blocos como uma UIImage.

GMSSyncTileLayer e GMSTileLayer são classes abstratas projetadas para serem subclasses. Você pode usar essas classes para servir blocos como UIImage. O exemplo abaixo mostra como renderizar uma imagem personalizada em alguns blocos no mapa criando subclasses de 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
      

Para adicionar a camada ao seu mapa, instancie o objeto e defina sua propriedade de mapa.

Swift

let layer = TestTileLayer()
layer.map = mapView
      

Objective-C

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

Blocos de DPI alto para dispositivos Retina

É possível usar imagens de DPI alto com GMSSyncTileLayer ou GMSURLTileLayer, definindo tileSize como 512. A propriedade tileSize indica o número de pixels que as imagens de bloco retornadas preferem mostrar. O padrão é 256, a dimensão de um bloco do Google Maps em um dispositivo sem Retina.

Se você está exibindo blocos com DPI normal em um dispositivo com DPI alto, é possível aumentar as imagens definindo tileSize como 512. O aumento do dimensionamento das imagens pode reduzir a qualidade, especialmente para linhas finas ou texto. Para melhores resultados, combine o tileSize e o DPI da imagem com a tela. Os mapas mostrados em dispositivos com tela Retina ficam melhores ao exibir imagens de alto DPI com um tileSize de 512. Já os mapas mostrados em dispositivos com tela Retina ficam incríveis com imagens normais e com o tileSize padrão de 256.

Limpeza de blocos desatualizados

Se os blocos fornecidos pela camada ficarem "desatualizados", o método clearTileCache vai precisar ser chamado na camada para forçar uma atualização. Isso faz com que todos os blocos dessa camada sejam recarregados.

Swift

layer.clearTileCache()
      

Objective-C

[layer clearTileCache];