É possível adicionar imagens sobre o mapa como uma camada de blocos. As camadas de blocos são colocadas sobre um bloco de mapa em um nível de zoom específico. Com blocos suficientes, você pode 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 nos blocos do mapa básico do Google. Essa é uma excelente maneira 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 que você substitua os dados de mapa de base do Google pelos seus.
As camadas de blocos são úteis para adicionar várias imagens ao mapa, geralmente cobrindo grandes áreas geográficas. Já as sobreposições de solo são úteis quando você quer corrigir uma única imagem em um ponto do mapa.
Coordenadas de bloco
A API Maps divide as imagens em cada nível de zoom em um conjunto de blocos de mapa quadrados, que são organizados em uma grade ordenada. Quando um mapa rola para um novo local ou para um novo nível de zoom, a API Maps determina quais blocos são necessários e os traduz em um conjunto de blocos a serem recuperados.
Para a implementação da projeção de Mercator do Google, o bloco com a coordenada (0,0) está 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 2 de zoom, quando a Terra é dividida em 16 blocos, cada bloco pode ser referenciado por um par x,y
exclusivo:
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 2 x 2 ou uma grade de 4 x 4 no nível 2, uma grade de 8 x 8 no nível 3 e assim por diante. Se você estiver criando imagens para uma camada de blocos, será necessário criar uma nova imagem de 256 x 256 pixels para cada bloco em cada nível de zoom que você quiser oferecer.
Adicionar uma camada de blocos
- Instanciar um objeto
GMSURLTileLayer
ou uma subclasse personalizada deGMSTileLayer
ouGMSSyncTileLayer
. - Modifique a propriedade
zIndex
, se quiser, para ajustar a posição dela em relação a outras camadas de blocos. - Atribua o objeto
GMSTileLayer
ao mapa definindo a propriedademap
.
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 de mapa correto para um determinado conjunto de coordenadas {x,y,zoom}
. As opções disponíveis são estas:
- Crie uma subclasse de
GMSSyncTileLayer
, fornecendo a implementação detileForX:y:zoom
que retorna instâncias deUIImage
. - Subclasse
GMSTileLayer
, fornecendo a implementação do método assíncronorequestTileForX:y:zoom
, que mais tarde faz uma chamada de volta com uma imagem de bloco. - Use a classe atual,
GMSURLTileLayer
, para buscar blocos automaticamente de URLs, fornecendo o blocoGMSTileURLConstructor
.GMSURLTileLayer
é uma classe concreta que não pode ser subclassificada.
No caso de subclassificação de GMSSyncTileLayer
ou GMSTileLayer
, fornecer um resultado de bloco nil
informa ao SDK do Maps para iOS que os dados não estão disponíveis no momento, mas podem estar disponíveis no futuro. Como alternativa,
retorne kGMSTileLayerNoTile
para indicar que não há bloco nesse
local.
Para GMSURLTileLayer
, o retorno de nil
da GMSTileURLConstructor
vai
indicar que não há bloco nesse local.
Usar GMSURLTileLayer para buscar blocos em URLs
O GMSURLTileLayer
não exige subclasses, mas você precisa
implementar o bloco GMSTileURLConstructor
. O código abaixo mostra como usar GMSURLTileLayer
para mostrar o plano 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;
Subclasse GMSSyncTileLayer para servir blocos como um UIImage
GMSSyncTileLayer
e GMSTileLayer
são classes abstratas projetadas para serem
subclasses. É possível usar essas classes para exibir blocos como UIImage
s. O exemplo abaixo mostra como renderizar uma imagem personalizada sobre alguns dos blocos no mapa subclassificando 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 alta DPI com GMSSyncTileLayer
ou GMSURLTileLayer
definindo o tileSize
como 512.
A propriedade tileSize
indica o número de pixels que as imagens de blocos retornadas vão preferir mostrar. O padrão é 256, a dimensão de um bloco do Google Maps em um dispositivo que não é Retina.
Se você estiver exibindo blocos de DPI normais em um dispositivo de DPI alto, poderá aumentar o
tamanho das imagens definindo tileSize
como 512. O escalonamento vertical pode reduzir a
qualidade da imagem, principalmente em linhas finas ou texto. Para resultados melhores, combine o
tileSize
e o DPI da imagem com a tela. Os mapas mostrados em um dispositivo Retina vão
ficar melhores ao exibir imagens de alta DPI com um tileSize
de 512.
Já os mapas mostrados em um dispositivo não Retina vão ficar ótimos com imagens normais
e o tileSize
padrão de 256.
Limpar blocos desatualizados
Se os blocos fornecidos pela camada ficarem "desatualizados", o método
clearTileCache
precisa ser chamado na camada para forçar uma atualização. Isso vai fazer com que todos os blocos dessa camada sejam recarregados.
Swift
layer.clearTileCache()
Objective-C
[layer clearTileCache];