Pronto!

Para começar a desenvolver, acesse nossa documentação do desenvolvedor.

Ativar a Google Maps JavaScript API

Para começar, orientaremos você pelo Console do Desenvolvedor do Google para realizar algumas atividades:

  1. Criar ou selecionar um projeto
  2. Ativar a Google Maps JavaScript API e serviços relacionados
  3. Criar chaves apropriadas
Continuar

Tipos de mapa

Tipos de mapa

Este documento discute os tipos de mapas que podem ser exibidos usando a Google Maps JavaScript API. A API usa um objeto MapType para manter as informações sobre esses mapas. Um MapType é uma interface que define a exibição e o uso de blocos de mapas e a conversão de sistemas de coordenadas de coordenadas de tela em coordenadas mundiais (no mapa). Cada MapType contém alguns métodos para processar a recuperação e a liberação de blocos, bem como propriedades que definem o comportamento visual.

O funcionamento interno dos tipos de mapa na Maps JavaScript API é um tópico avançado. Para a maioria dos desenvolvedores, é suficiente usar os tipos de mapas básicos descritos abaixo. No entanto, também é possível definir seus próprios blocos de mapas usando tipos de mapa personalizados ou modificar a apresentação de tipos de mapa existentes usando Mapas estilizados. Para fornecer tipos de mapa personalizados, é necessário compreender como modificar o registro de tipo de mapa do mapa.

Tipos de mapa básicos

Há quatro tipos de mapas disponíveis na Google Maps JavaScript API. Além dos blocos de mapa de estrada "pintados" comuns, a Maps JavaScript API também suporta outros tipos de mapa.

Os tipos de mapa a seguir estão disponíveis na Maps JavaScript API:

  • roadmap exibe o mapa de vias padrão. Esse é o tipo de mapa padrão.
  • satellite exibe imagens de satélite do Google Earth
  • hybrid exibe uma combinação de visualizações normais e de satélite
  • terrain exibe um mapa físico baseado em informações do terreno.

Modifique o tipo de mapa usado pelo Map definindo a propriedade mapTypeId. Isso pode ser feito no construtor, definindo o objeto Map options ou chamando o método setMapTypeId() do mapa. A propriedade mapTypeID tem roadmap definido como padrão.

Definir o mapTypeId na construção:

var myLatlng = new google.maps.LatLng(-34.397, 150.644);
var mapOptions = {
  zoom: 8,
  center: myLatlng,
  mapTypeId: 'satellite'
};
var map = new google.maps.Map(document.getElementById('map'),
    mapOptions);

Modificar o mapTypeId dinamicamente:

map.setMapTypeId('terrain');

Observe que o tipo do mapa não é definindo diretamente no mapa. Em vez disso, defina o mapTypeId do mapa para referenciar um MapType usando um identificador. A Maps JavaScript API usa um registro de tipo de mapa, explicado abaixo, para gerenciar essas referências.

Imagens de 45°

A Google Maps JavaScript API permite imagens especiais de 45° para determinadas localizações. Essas imagens de alta resolução oferecem visualizações de perspectiva na direção de cada ponto cardeal (norte, sul, leste e oeste). Essas imagens estão disponíveis em níveis de resolução mais altos para os tipos de mapa permitidos.

A imagem a seguir mostra uma visualização de perspectiva de 45° do calçadão em Santa Cruz, Califórnia, EUA:

Os tipos de mapa satellite e hybrid permitem imagens de 45° em níveis altos de zoom, onde disponíveis. Se o usuário aumenta o zoom em uma localização onde existem essas imagens, esses tipos de mapa alteram automaticamente a visualização da seguinte forma:

  • As imagens de satélite ou híbridas são substituídas por imagens com uma perspectiva de 45° centralizada na localização atual. Por padrão, essas visualizações são orientadas para o norte. Se o usuário reduzir o zoom, as imagens de satélite ou híbridas padrão são exibidas novamente.
  • O controle Rotate oferece uma combinação de opções de inclinação e rotação. Se rotateControl for true, aparecerá um controle de inclinação quando houver imagens 45° disponíveis. O controle de inclinação permite que o usuário incline as imagens em um ângulo de 45°.
  • Quando a imagem é inclinada, aparece um gancho, permitindo que os usuários girem a visualização 90° no sentido horário.

A redução do zoom de um tipo de mapa que exibe imagens de 45° reverte todas essas alterações, restabelecendo os tipos de mapa originais.

Ativar e desativar imagens de 45°

É possível desativar imagens de 45° chamando setTilt(0) no objeto Map. Para ativar imagens de 45° para os tipos de mapa suportados, chame setTilt(45).

O método getTilt() do Map sempre reflete a inclinação atual mostrada no mapa. Se você definir uma inclinação em um mapa e depois removê-la (por exemplo, reduzindo o zoom), o método getTilt() do mapa retornará 0.

O exemplo a seguir exibe uma visualização de 45° do centro de Portland, Oregon, EUA:

function initMap() {
  var map = new google.maps.Map(document.getElementById('map'), {
    center: {lat: 36.964, lng: -122.015},
    zoom: 18,
    mapTypeId: 'satellite'
  });
  map.setTilt(45);
}
<div id="map"></div>
/* Always set the map height explicitly to define the size of the div
 * element that contains the map. */
#map {
  height: 100%;
}
/* Optional: Makes the sample page fill the window. */
html, body {
  height: 100%;
  margin: 0;
  padding: 0;
}
 <!-- Replace the value of the key parameter with your own API key. -->
<script async defer
src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap">
</script>
function initMap() {
  var map = new google.maps.Map(document.getElementById('map'), {
    center: {lat: 36.964, lng: -122.015},
    zoom: 18,
    mapTypeId: 'satellite'
  });
  map.setTilt(45);
}

Ver o exemplo (aerial-simple.html).

Girar imagens de 45°

Na verdade, as imagens de 45° consistem em uma coleção de imagens para cada ponto cardeal (norte, sul, leste e oeste). Quando o mapa exibe imagens de 45°, oriente as imagens na direção de um dos pontos cardeais chamando setHeading() no objeto Map, passando um valor numérico expresso em graus em relação ao norte.

O exemplo a seguir mostra um mapa aéreo e gira automaticamente o mapa a cada três segundos quando o botão é clicado:

var map;

function initMap() {
  map = new google.maps.Map(document.getElementById('map'), {
    center: {lat: 45.518, lng: -122.672},
    zoom: 18,
    mapTypeId: 'satellite',
    heading: 90,
    tilt: 45
  });
}

function rotate90() {
  var heading = map.getHeading() || 0;
  map.setHeading(heading + 90);
}

function autoRotate() {
  // Determine if we're showing aerial imagery.
  if (map.getTilt() !== 0) {
    window.setInterval(rotate90, 3000);
  }
}
<div id="floating-panel"><input type="button" value="Auto Rotate" onclick="autoRotate();"></div>
<div id="map"></div>
/* Always set the map height explicitly to define the size of the div
 * element that contains the map. */
#map {
  height: 100%;
}
/* Optional: Makes the sample page fill the window. */
html, body {
  height: 100%;
  margin: 0;
  padding: 0;
}
#floating-panel {
  position: absolute;
  top: 10px;
  left: 25%;
  z-index: 5;
  background-color: #fff;
  padding: 5px;
  border: 1px solid #999;
  text-align: center;
  font-family: 'Roboto','sans-serif';
  line-height: 30px;
  padding-left: 10px;
}
 <!-- Replace the value of the key parameter with your own API key. -->
<script async defer
src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap">
</script>
var map;

function initMap() {
  map = new google.maps.Map(document.getElementById('map'), {
    center: {lat: 45.518, lng: -122.672},
    zoom: 18,
    mapTypeId: 'satellite',
    heading: 90,
    tilt: 45
  });
}

function rotate90() {
  var heading = map.getHeading() || 0;
  map.setHeading(heading + 90);
}

function autoRotate() {
  // Determine if we're showing aerial imagery.
  if (map.getTilt() !== 0) {
    window.setInterval(rotate90, 3000);
  }
}

Ver o exemplo (aerial-rotation.html).

Modificar o registro de tipo de mapa

O mapTypeId é um identificador de string usado para associar um MapType a um valor único. Cada objeto Map mantém um MapTypeRegistry, que contém a coleção de MapType disponível para esse mapa. Por exemplo, esse registro é usado para selecionar os tipos de mapas disponíveis no controle MapType do mapa.

O registro de tipos de mapa não é lido diretamente. Em vez disso, modifique o registro adicionando tipos de mapa personalizados e associando-os a um identificador de string de sua escolha. Não é possível modificar nem alterar os tipos de mapa básicos (embora seja possível removê-los do mapa alterando a aparência das mapTypeControlOptions associadas do mapa.

O código a seguir configura o mapa para mostrar apenas dois tipos de mapa nas mapTypeControlOptions e modifica o registro para adicionar a associação com o identificador à implementação real da interface MapType. Observação: propositadamente, não documentamos a criação do tipo de mapa personalizado no código anterior. Consulte Mapas estilizados ou Tipos de mapa personalizados abaixo para obter informações sobre a construção de um tipo de mapa.

// Modify the control to only display two maptypes, the
// default ROADMAP and the custom 'mymap'.
// Note that because this is simply an association, we
// don't need to modify the MapTypeRegistry beforehand.

var MY_MAPTYPE_ID = 'mymaps';

var mapOptions = {
  zoom: 12,
  center: brooklyn,
  mapTypeControlOptions: {
     mapTypeIds: ['roadmap', MY_MAPTYPE_ID]
  },
  mapTypeId: MY_MAPTYPE_ID
};

// Create our map. This creation will implicitly create a
// map type registry.
map = new google.maps.Map(document.getElementById('map'),
    mapOptions);

// Create your custom map type using your own code.
// (See below.)
var myMapType = new MyMapType();

// Set the registry to associate 'mymap' with the
// custom map type we created, and set the map to
// show that map type.
map.mapTypes.set(MY_MAPTYPE_ID, myMapType);

Mapas estilizados

O StyledMapType permite personalizar a apresentação dos mapas padrão do Google, alterando a exibição visual de elementos como vias, parques e áreas construídas para refletir um estilo diferente do usado no tipo de mapa padrão.

Para obter mais informações sobre o StyledMapType, consulte o guia de mapas estilizados.

Tipos de mapa personalizados

A Google Maps JavaScript API permite exibir e administrar os tipos de mapa personalizados, possibilitando a implementação de suas próprias imagens de mapa ou sobreposição de blocos.

Há várias implementações de tipo de mapa possíveis na Maps JavaScript API:

  • Conjuntos de blocos compostos de imagens que, coletivamente, constituem mapas cartográficos completos. Esses conjuntos de blocos também são conhecidos como tipos de mapa básicos. Os tipos de mapa a seguir atuam e comportam-se como os tipos de mapa padrão existentes: roadmap, satellite, hybrid e terrain. Adicione seu tipo de mapa personalizado à matriz de mapTypes de um mapa para permitir que a IU na Maps JavaScript API trate seu tipo de mapa personalizado como um tipo padrão (por exemplo, incluindo-o no controle MapType).
  • Sobreposições de blocos de imagem, exibidas acima dos tipos de mapa básicos atuais. Geralmente, esses tipos de mapa são usados para aprimorar um tipo de mapa existente com a exibição de informações adicionais. Muitas vezes, são restritos a localizações e/ou níveis de zoom específicos. Observe que esses blocos podem ser transparentes, permitindo adicionar recursos a mapas existentes.
  • Tipos de mapa sem imagens, que permitem manipular a exibição de informações do mapa no nível mais básico.

Todas essas opções dependem da criação de uma classe que implementa a interface MapType. Além disso, a classe ImageMapType fornece alguns comportamentos incorporados para simplificar a criação de MapType de imagens.

Antes de explicar as classes que implementam o MapType, é importante compreender como o Google Maps determina as coordenadas e decide quais partes do mapa são exibidas. É necessário implementar lógica semelhante para todos os MapType básicos ou de sobreposição.

Coordenadas de mapa

Há vários sistemas de coordenadas que a Google Maps JavaScript API usa:

  • Valores de latitude e longitude, que referenciam exclusivamente um ponto no mundo. (O Google usa o padrão World Geodetic System WGS84.)
  • Coordenadas mundiais, que referenciam exclusivamente um ponto no mapa
  • Coordenadas de bloco, que referenciam um bloco específico no mapa com um determinado nível de zoom

Coordenadas mundiais

Sempre que a Google Maps JavaScript API precisa converter uma localização mundial em uma localização em um mapa (a tela), ela precisa antes converter valores de latitude e longitude em uma coordenada "mundial". Essa conversão é realizada usando uma projeção de mapa. O Google Maps usa a projeção Mercator para essa finalidade. Também é possível definir a sua própria projeção, implementando a interface google.maps.Projection. (Observe que as interfaces na Maps JavaScript API não são classes obtidas pela criação de subclasses, mas apenas especificações de classes que você mesmo define.)

Para maior conveniência no cálculo de coordenadas de pixel (veja abaixo), supomos que um mapa no nível de zoom 0 é um único bloco com o tamanho do bloco básico. Em seguida, definimos coordenadas mundiais em relação às coordenadas de pixel no nível de zoom 0, usando a projeção para converter latitudes e longitudes em posições de pixel nesse bloco básico. Essa coordenada mundial é um valor de ponto flutuante, medido da origem da projeção do mapa até a localização específica. Observe que, como esse valor é um número de ponto flutuante, pode ser muito mais preciso que a resolução atual da imagem do mapa exibida. Em outras palavras, uma coordenada mundial é independente do nível de zoom atual.

As coordenadas mundiais no Google Maps são medidas da origem da projeção Mercator (o canto noroeste do mapa a 180 graus de longitude e aproximadamente 85 graus de latitude) e aumentam na direção x rumo ao leste (direita) e na direção y rumo ao sul (para baixo). Como o bloco básico Mercator do Google Maps tem 256 x 256 pixels, o espaço de coordenadas mundiais usável é {0-256}, {0-256} (veja abaixo.)

Observe que uma projeção Mercator tem largura finita no sentido longitudinal, mas altura infinita no sentido latitudinal. As imagens do mapa básico são "cortadas" usando a projeção Mercator a aproximadamente +/- 85 graus para que o mapa resultante tenha um formato quadrado, facilitando a lógica da seleção de blocos. Observe que uma projeção pode gerar coordenadas mundiais fora do espaço de coordenadas usável do mapa. Por exemplo, plotagens muito próximas dos polos.

Coordenadas de pixel

As coordenadas mundiais refletem localizações absolutas em uma determinada projeção, mas precisamos convertê-las em coordenadas de pixel para determinar o deslocamento do "pixel" em um nível de zoom específico. Essas coordenadas de pixel são calculadas usando a fórmula a seguir:

pixelCoordinate = worldCoordinate * 2zoomLevel

Na equação acima, observe que cada incremento de nível de zoom é duas vezes maior nas direções x e y. Portanto, cada incremento de nível de zoom contém quatro vezes mais resolução que o nível anterior. Por exemplo, no nível de zoom 1, o mapa consiste em 4 blocos de 256x256 pixels, resultando em um espaço de pixels de 512x512. No nível de zoom 19, cada pixel em x e y no mapa pode ser referenciado usando um valor entre 0 e 256 * 219

Como baseamos as coordenadas mundiais no tamanho do bloco do mapa, a parte inteira das coordenadas do pixel identifica o pixel exato naquela localização no nível de zoom atual. Observe que as coordenadas de pixel são iguais às coordenadas mundiais no nível de zoom 0.

Agora, podemos identificar precisamente todas as localizações no mapa em todos os níveis de zoom. A Google Maps JavaScript API cria uma janela de visualização considerando o centro do nível de zoom do mapa (como uma LatLng) e o tamanho do elemento DOM que a contém, convertendo essa caixa limitadora em coordenadas de pixel. Em seguida, a API determina logicamente todos os blocos de mapa posicionados dentro dos limites de pixel informados. Cada bloco de mapa é referenciado usando coordenadas de bloco, que simplificam consideravelmente a exibição de imagens do mapa.

Coordenadas de bloco

A Google Maps JavaScript API não consegue carregar todas as imagens de mapa mais úteis em níveis de zoom mais altos. Em vez disso, a Maps JavaScript API divide as imagens em cada nível de zoom em um conjunto de blocos de mapa, organizados logicamente em uma ordem compreendida pelo aplicativo. Quando um mapa rola para uma nova localização ou para um novo nível de zoom, a Maps JavaScript API determina quais blocos são necessários usando coordenadas de pixel e converte esses valores em um conjunto de blocos a recuperar. Essas coordenadas de blocos são atribuídas usando um esquema que facilita a lógica da determinação de qual bloco contém a imagem de um ponto específico.

Os blocos no Google Maps são numerados a partir da mesma origem dos pixels. Para a implementação da projeção Mercator no Google, o bloco de origem está sempre no canto noroeste do mapa, com os valores de x aumentando de oeste para leste e de y de norte para sul. Os blocos são indexados usando as coordenadas x, y daquela origem. Por exemplo, no nível de zoom 2, quando o planeta é dividido em 16 blocos, cada bloco pode ser referenciado por um par x, y único:

Observe que, ao dividir as coordenadas de pixel pelo tamanho do bloco e considerar as partes inteiras do resultado, um resultado adicional é a obtenção da coordenada do bloco no nível de zoom atual.

O exemplo a seguir exibe coordenadas (valores de LatLng, coordenadas mundiais coordenadas de pixel e coordenadas de bloco) para Chicago, Illinois, EUA, em diferentes níveis de zoom.

Ver o exemplo (map-coordinates.html)

A interface MapType

Os tipos de mapa personalizados precisam implementam a interface MapType. Essa interface especifica determinadas propriedades e métodos que permitem que a API inicialize solicitações para os seus tipos de mapas quando determina que é necessário exibir blocos de mapa dentro da porta de visualização e do nível de zoom atuais. Essas solicitações são processadas para decidir o bloco a ser carregado.

Observação: Você pode criar a própria classe para implementar essa interface ou, se tiver imagens compatíveis, use a classe ImageMapType que já implementa essa interface.)

As classes que implementam a interface MapType exigem a definição e o preenchimento das seguintes propriedades:

  • tileSize (obrigatória) especifica o tamanho do bloco (do tipo google.maps.Size). Os tamanhos precisam ser retangulares, mas não necessariamente quadrados.
  • maxZoom (obrigatória) especifica o nível máximo de zoom para exibição de blocos desse tipo de mapa.
  • minZoom (opcional) especifica o nível mínimo de zoom para exibição de blocos desse tipo de mapa. Por padrão, esse valor é 0, o que indica que não existe mínimo nível de zoom.
  • name (opcional) especifica o nome desse tipo de mapa. Essa propriedade somente é necessária se esse tipo de mapa é selecionável em um controle MapType. (Consulte Adicionar controles MapType abaixo.)
  • alt (opcional) especifica o texto alternativo para esse tipo de mapa, exibido como texto na focalização. Essa propriedade somente é necessária se esse tipo de mapa é selecionável em um controle MapType. (Consulte Adicionar controles MapType abaixo.)

Além disso, as classes que implementam a interface MapType precisam implementar os seguintes métodos:

  • getTile() (obrigatório) é chamado sempre que a API determina que o mapa precisa exibir novos blocos para a porta de visualização especificada. O método getTile() precisa ter a seguinte assinatura:

    getTile(tileCoord:Point,zoom:number,ownerDocument:Document):Node

    A API determina a necessidade de chamar getTile() de acordo com as propriedades tileSize, minZoom e maxZoom de MapType e com a porta de visualização e o nível de zoom atuais do mapa. Usando as informações passadas de coordenada, do nível de zoom e do elemento DOM onde a imagem do bloco será anexada, o manipulador desse método retorna um elemento HTML.

  • releaseTile() (opcional) é chamado sempre que a API determina que o mapa precisa remover um bloco ao ficar fora da visualização. Esse método precisa ter a seguinte assinatura:

    releaseTile(tile:Node)

    Normalmente, você é responsável por remover todos os elementos anexados a blocos de mapa na adição ao mapa. Por exemplo, se você anexou ouvintes de eventos às sobreposições de blocos do mapa, precisará removê-los aqui.

O método getTile() age como o principal controlador para determinar os blocos a carregar em uma porta de visualização específica.

Tipos de mapa básicos

Os tipos de mapa construídos dessa forma podem ser independentes ou combinados com outros tipos de mapa como sobreposições. Os tipos de mapa independentes são conhecidos como tipos de mapa básicos. Pode ser necessário que a API trate esses MapType personalizados como qualquer outro tipo de mapa básico existente (ROADMAP, TERRAIN etc.). Para isso, adicione o MapType personalizado à propriedade mapTypes do Map. Essa propriedade é do tipo MapTypeRegistry.

O código a seguir cria um MapType básico para exibir as coordenadas de bloco de um mapa e desenha um contorno dos blocos:

/*
 * This demo demonstrates how to replace default map tiles with custom imagery.
 * In this case, the CoordMapType displays gray tiles annotated with the tile
 * coordinates.
 *
 * Try panning and zooming the map to see how the coordinates change.
 */

/**
 * @constructor
 * @implements {google.maps.MapType}
 */
function CoordMapType(tileSize) {
  this.tileSize = tileSize;
}

CoordMapType.prototype.maxZoom = 19;
CoordMapType.prototype.name = 'Tile #s';
CoordMapType.prototype.alt = 'Tile Coordinate Map Type';

CoordMapType.prototype.getTile = function(coord, zoom, ownerDocument) {
  var div = ownerDocument.createElement('div');
  div.innerHTML = coord;
  div.style.width = this.tileSize.width + 'px';
  div.style.height = this.tileSize.height + 'px';
  div.style.fontSize = '10';
  div.style.borderStyle = 'solid';
  div.style.borderWidth = '1px';
  div.style.borderColor = '#AAAAAA';
  div.style.backgroundColor = '#E5E3DF';
  return div;
};

function initMap() {
  var map = new google.maps.Map(document.getElementById('map'), {
    zoom: 10,
    center: {lat: 41.850, lng: -87.650},
    streetViewControl: false,
    mapTypeId: 'coordinate',
    mapTypeControlOptions: {
      mapTypeIds: ['coordinate', 'roadmap'],
      style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
    }
  });

  map.addListener('maptypeid_changed', function() {
    var showStreetViewControl = map.getMapTypeId() !== 'coordinate';
    map.setOptions({
      streetViewControl: showStreetViewControl
    });
  });

  // Now attach the coordinate map type to the map's registry.
  map.mapTypes.set('coordinate',
                   new CoordMapType(new google.maps.Size(256, 256)));
}
<div id="map"></div>
/* Always set the map height explicitly to define the size of the div
 * element that contains the map. */
#map {
  height: 100%;
}
/* Optional: Makes the sample page fill the window. */
html, body {
  height: 100%;
  margin: 0;
  padding: 0;
}
 <!-- Replace the value of the key parameter with your own API key. -->
<script async defer
src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap">
</script>
/*
 * This demo demonstrates how to replace default map tiles with custom imagery.
 * In this case, the CoordMapType displays gray tiles annotated with the tile
 * coordinates.
 *
 * Try panning and zooming the map to see how the coordinates change.
 */

/**
 * @constructor
 * @implements {google.maps.MapType}
 */
function CoordMapType(tileSize) {
  this.tileSize = tileSize;
}

CoordMapType.prototype.maxZoom = 19;
CoordMapType.prototype.name = 'Tile #s';
CoordMapType.prototype.alt = 'Tile Coordinate Map Type';

CoordMapType.prototype.getTile = function(coord, zoom, ownerDocument) {
  var div = ownerDocument.createElement('div');
  div.innerHTML = coord;
  div.style.width = this.tileSize.width + 'px';
  div.style.height = this.tileSize.height + 'px';
  div.style.fontSize = '10';
  div.style.borderStyle = 'solid';
  div.style.borderWidth = '1px';
  div.style.borderColor = '#AAAAAA';
  div.style.backgroundColor = '#E5E3DF';
  return div;
};

function initMap() {
  var map = new google.maps.Map(document.getElementById('map'), {
    zoom: 10,
    center: {lat: 41.850, lng: -87.650},
    streetViewControl: false,
    mapTypeId: 'coordinate',
    mapTypeControlOptions: {
      mapTypeIds: ['coordinate', 'roadmap'],
      style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
    }
  });

  map.addListener('maptypeid_changed', function() {
    var showStreetViewControl = map.getMapTypeId() !== 'coordinate';
    map.setOptions({
      streetViewControl: showStreetViewControl
    });
  });

  // Now attach the coordinate map type to the map's registry.
  map.mapTypes.set('coordinate',
                   new CoordMapType(new google.maps.Size(256, 256)));
}

Ver o exemplo (maptype-base.html).

Tipos de mapa de sobreposição

Alguns tipos de mapa são projetados para funcionar sobre tipos de mapa existentes. Esses tipos de mapa podem ter camadas transparentes indicando pontos de interesse ou mostrando dados adicionais ao usuário.

Nesses casos, não é adequado tratar o tipo de mapa como uma entidade separada. Em vez disso, adicione diretamente o tipo de mapa a um MapType existente usando a propriedade overlayMapTypes do Map. Essa propriedade contém uma MVCArray de MapType. Todos os tipos de mapa (básico e de sobreposição) são renderizados na camada mapPane. Os tipos de mapa de sobreposição são exibidos acima de todos os mapas básicos aos quais estão anexados na ordem em que aparecem na matriz Map.overlayMapTypes.

O exemplo a seguir é idêntico ao anterior, exceto pela criação de um MapType de sobreposição de blocos acima do tipo de mapa ROADMAP:

/*
 * This demo illustrates the coordinate system used to display map tiles in the
 * API.
 *
 * Tiles in Google Maps are numbered from the same origin as that for
 * pixels. For Google's implementation of the Mercator projection, the origin
 * tile is always at the northwest corner of the map, with x values increasing
 * from west to east and y values increasing from north to south.
 *
 * Try panning and zooming the map to see how the coordinates change.
 */

/** @constructor */
function CoordMapType(tileSize) {
  this.tileSize = tileSize;
}

CoordMapType.prototype.getTile = function(coord, zoom, ownerDocument) {
  var div = ownerDocument.createElement('div');
  div.innerHTML = coord;
  div.style.width = this.tileSize.width + 'px';
  div.style.height = this.tileSize.height + 'px';
  div.style.fontSize = '10';
  div.style.borderStyle = 'solid';
  div.style.borderWidth = '1px';
  div.style.borderColor = '#AAAAAA';
  return div;
};

function initMap() {
  var map = new google.maps.Map(document.getElementById('map'), {
    zoom: 10,
    center: {lat: 41.850, lng: -87.650}
  });

  // Insert this overlay map type as the first overlay map type at
  // position 0. Note that all overlay map types appear on top of
  // their parent base map.
  map.overlayMapTypes.insertAt(
      0, new CoordMapType(new google.maps.Size(256, 256)));
}
<div id="map"></div>
/* Always set the map height explicitly to define the size of the div
 * element that contains the map. */
#map {
  height: 100%;
}
/* Optional: Makes the sample page fill the window. */
html, body {
  height: 100%;
  margin: 0;
  padding: 0;
}
 <!-- Replace the value of the key parameter with your own API key. -->
<script async defer
src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap">
</script>
/*
 * This demo illustrates the coordinate system used to display map tiles in the
 * API.
 *
 * Tiles in Google Maps are numbered from the same origin as that for
 * pixels. For Google's implementation of the Mercator projection, the origin
 * tile is always at the northwest corner of the map, with x values increasing
 * from west to east and y values increasing from north to south.
 *
 * Try panning and zooming the map to see how the coordinates change.
 */

/** @constructor */
function CoordMapType(tileSize) {
  this.tileSize = tileSize;
}

CoordMapType.prototype.getTile = function(coord, zoom, ownerDocument) {
  var div = ownerDocument.createElement('div');
  div.innerHTML = coord;
  div.style.width = this.tileSize.width + 'px';
  div.style.height = this.tileSize.height + 'px';
  div.style.fontSize = '10';
  div.style.borderStyle = 'solid';
  div.style.borderWidth = '1px';
  div.style.borderColor = '#AAAAAA';
  return div;
};

function initMap() {
  var map = new google.maps.Map(document.getElementById('map'), {
    zoom: 10,
    center: {lat: 41.850, lng: -87.650}
  });

  // Insert this overlay map type as the first overlay map type at
  // position 0. Note that all overlay map types appear on top of
  // their parent base map.
  map.overlayMapTypes.insertAt(
      0, new CoordMapType(new google.maps.Size(256, 256)));
}

Ver o exemplo (maptype-overlay.html).

Tipos de mapa de imagem

A implementação de um MapType para atuar como um tipo de mapa básico pode ser uma tarefa demorada e trabalhosa. Essa API oferece uma classe especial que implementa a interface MapType para os tipos de mapa mais comuns: os que consistem em blocos compostos de um único arquivo de imagem.

Essa classe, ImageMapType, é construída usando uma especificação de objeto ImageMapTypeOptions definindo as propriedades obrigatórias a seguir:

  • tileSize (obrigatória) especifica o tamanho do bloco (do tipo google.maps.Size). Os tamanhos precisam ser retangulares, mas não necessariamente quadrados.
  • getTileUrl (obrigatória) especifica a função, normalmente fornecida como um literal de função em linha, para processar a seleção do bloco de imagem adequado de acordo com as coordenadas mundiais e o nível de zoom fornecidos.

O código a seguir implementa um ImageMapType básico usando os blocos da lua do Google. O exemplo usa uma função de normalização para garantir que os blocos sejam repetidos ao longo do eixo x do mapa, mas não ao longo do eixo y.

function initMap() {
  var map = new google.maps.Map(document.getElementById('map'), {
    center: {lat: 0, lng: 0},
    zoom: 1,
    streetViewControl: false,
    mapTypeControlOptions: {
      mapTypeIds: ['moon']
    }
  });

  var moonMapType = new google.maps.ImageMapType({
    getTileUrl: function(coord, zoom) {
        var normalizedCoord = getNormalizedCoord(coord, zoom);
        if (!normalizedCoord) {
          return null;
        }
        var bound = Math.pow(2, zoom);
        return '//mw1.google.com/mw-planetary/lunar/lunarmaps_v1/clem_bw' +
            '/' + zoom + '/' + normalizedCoord.x + '/' +
            (bound - normalizedCoord.y - 1) + '.jpg';
    },
    tileSize: new google.maps.Size(256, 256),
    maxZoom: 9,
    minZoom: 0,
    radius: 1738000,
    name: 'Moon'
  });

  map.mapTypes.set('moon', moonMapType);
  map.setMapTypeId('moon');
}

// Normalizes the coords that tiles repeat across the x axis (horizontally)
// like the standard Google map tiles.
function getNormalizedCoord(coord, zoom) {
  var y = coord.y;
  var x = coord.x;

  // tile range in one direction range is dependent on zoom level
  // 0 = 1 tile, 1 = 2 tiles, 2 = 4 tiles, 3 = 8 tiles, etc
  var tileRange = 1 << zoom;

  // don't repeat across y-axis (vertically)
  if (y < 0 || y >= tileRange) {
    return null;
  }

  // repeat across x-axis
  if (x < 0 || x >= tileRange) {
    x = (x % tileRange + tileRange) % tileRange;
  }

  return {x: x, y: y};
}
<div id="map"></div>
/* Always set the map height explicitly to define the size of the div
 * element that contains the map. */
#map {
  height: 100%;
}
/* Optional: Makes the sample page fill the window. */
html, body {
  height: 100%;
  margin: 0;
  padding: 0;
}
 <!-- Replace the value of the key parameter with your own API key. -->
<script async defer
src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap">
</script>
function initMap() {
  var map = new google.maps.Map(document.getElementById('map'), {
    center: {lat: 0, lng: 0},
    zoom: 1,
    streetViewControl: false,
    mapTypeControlOptions: {
      mapTypeIds: ['moon']
    }
  });

  var moonMapType = new google.maps.ImageMapType({
    getTileUrl: function(coord, zoom) {
        var normalizedCoord = getNormalizedCoord(coord, zoom);
        if (!normalizedCoord) {
          return null;
        }
        var bound = Math.pow(2, zoom);
        return '//mw1.google.com/mw-planetary/lunar/lunarmaps_v1/clem_bw' +
            '/' + zoom + '/' + normalizedCoord.x + '/' +
            (bound - normalizedCoord.y - 1) + '.jpg';
    },
    tileSize: new google.maps.Size(256, 256),
    maxZoom: 9,
    minZoom: 0,
    radius: 1738000,
    name: 'Moon'
  });

  map.mapTypes.set('moon', moonMapType);
  map.setMapTypeId('moon');
}

// Normalizes the coords that tiles repeat across the x axis (horizontally)
// like the standard Google map tiles.
function getNormalizedCoord(coord, zoom) {
  var y = coord.y;
  var x = coord.x;

  // tile range in one direction range is dependent on zoom level
  // 0 = 1 tile, 1 = 2 tiles, 2 = 4 tiles, 3 = 8 tiles, etc
  var tileRange = 1 << zoom;

  // don't repeat across y-axis (vertically)
  if (y < 0 || y >= tileRange) {
    return null;
  }

  // repeat across x-axis
  if (x < 0 || x >= tileRange) {
    x = (x % tileRange + tileRange) % tileRange;
  }

  return {x: x, y: y};
}

Ver o exemplo (maptype-image.html).

Projeções

A Terra é uma esfera tridimensional (aproximadamente) e o mapa é uma superfície bidimensional plana. O mapa exibido pela Google Maps JavaScript API, como qualquer outro mapa plano da Terra, é uma projeção dessa esfera em uma superfície plana. Nos termos mais simples, uma projeção pode ser definida como o mapeamento de valores de latitude/longitude em coordenadas no mapa da projeção.

As projeções na Maps JavaScript API devem implementar a interface Projection. Uma implementação Projection fornece não apenas um mapeamento de um sistema de coordenadas para outro, mas um mapeamento bidirecional. Ou seja, você define como converter as coordenadas da Terra (LatLngs) no sistema de coordenadas mundiais da Projection e vice-versa. O Google Maps usa a projeção Mercator para criar mapas de dados geográficos e converter eventos no mapa em coordenadas geográficas. Obtenha essa projeção chamando getProjection() no Map (ou em qualquer dos MapType básicos padrão.) Essa Projection padrão é suficiente para a maioria dos usos, mas é possível definir e usar suas projeções personalizadas.

Implementar uma projeção

Ao implementar uma projeção personalizada, algumas definições são necessárias:

  • As fórmulas para mapear coordenadas de latitude e longitude em um plano cartesiano e vice-versa. (A interface Projection permite apenas transformações para coordenadas retilíneas.)
  • O tamanho de bloco básico. Todos os blocos precisam ser retangulares.
  • O "tamanho do mundo" de um mapa usando o conjunto de blocos básico no nível de zoom 0. Observe que, nos mapas compostos de um bloco em zoom 0, o tamanho do mundo e o tamanho do bloco básico são idênticos.

Transformações de coordenadas em projeções

Cada projeção oferece dois métodos de conversão entre os dois sistemas de coordenadas: geográficas e mundiais.

  • O método Projection.fromLatLngToPoint() converte um valor LatLng em uma coordenada mundial. Esse método é usado para posicionar sobreposições no mapa (e para posicionar o próprio mapa).
  • O método Projection.fromPointToLatLng() converte uma coordenada mundial em um valor LatLng. Esse método é usado para converter eventos ocorridos no mapa, como cliques, em coordenadas geográficas.

O Google Maps assume que as projeções são retilíneas.

Geralmente, a projeção é usada em dois casos: para criar um mapa do mundo ou para criar um mapa de uma área local. No primeiro caso, é necessário assegurar que a projeção seja retilínea e normal em todas as longitudes. Algumas projeções (particularmente as projeções cônicas) podem ser "localmente normais" (ou seja, apontar para o norte), mas desviar do norte verdadeiro. Por exemplo, quando o mapa é posicionado longe em relação a alguma longitude de referência. Essa projeção pode ser usada localmente. No entanto, observe que ela será necessariamente imprecisa e os erros de transformação ficarão cada vez mais evidentes à medida que a projeção se afastar da longitude de referência.

Seleção de blocos de mapa em projeções

Além de determinar as posições de localizações ou sobreposições, as projeções também são úteis para posicionar os próprios blocos de mapa. A Google Maps JavaScript API renderiza os mapas básicos usando uma interface MapType, que declara uma propriedade projection para identificar a projeção do mapa, e um método getTile() para recuperar blocos de mapa de acordo com os valores da coordenada do bloco. As coordenadas do bloco são baseadas no tamanho do bloco básico (que precisa ser retangular) e no "tamanho do mundo" do mapa, que é o tamanho em pixels do mapa do mundo no nível de zoom 0. (Para mapas compostos de um bloco em zoom 0, o tamanho do mundo e o tamanho do bloco básico são idênticos.)

Defina o tamanho do bloco básico na propriedade tileSize de MapType. O tamanho do mundo é definido implicitamente nos métodos fromLatLngToPoint() e fromPointToLatLng() da projeção.

Como a seleção de imagens depende desses valores passados, é útil atribuir às imagens nomes que possam ser selecionados programaticamente considerando esses valores passados, como map_zoom_tileX_tileY.png.

O exemplo a seguir define um ImageMapType usando a projeção Gall-Peters:

// This example defines an image map type using the Gall-Peters
// projection.
// https://en.wikipedia.org/wiki/Gall%E2%80%93Peters_projection

function initMap() {
  // Create a map. Use the Gall-Peters map type.
  var map = new google.maps.Map(document.getElementById('map'), {
    zoom: 0,
    center: {lat: 0, lng: 0},
    mapTypeControl: false
  });

  initGallPeters();
  map.mapTypes.set('gallPeters', gallPetersMapType);
  map.setMapTypeId('gallPeters');

  // Show the lat and lng under the mouse cursor.
  var coordsDiv = document.getElementById('coords');
  map.controls[google.maps.ControlPosition.TOP_CENTER].push(coordsDiv);
  map.addListener('mousemove', function(event) {
    coordsDiv.textContent =
        'lat: ' + Math.round(event.latLng.lat()) + ', ' +
        'lng: ' + Math.round(event.latLng.lng());
  });

  // Add some markers to the map.
  map.data.setStyle(function(feature) {
    return {
      title: feature.getProperty('name'),
      optimized: false
    };
  });
  map.data.addGeoJson(cities);
}

var gallPetersMapType;
function initGallPeters() {
  var GALL_PETERS_RANGE_X = 800;
  var GALL_PETERS_RANGE_Y = 512;

  // Fetch Gall-Peters tiles stored locally on our server.
  gallPetersMapType = new google.maps.ImageMapType({
    getTileUrl: function(coord, zoom) {
      var scale = 1 << zoom;

      // Wrap tiles horizontally.
      var x = ((coord.x % scale) + scale) % scale;

      // Don't wrap tiles vertically.
      var y = coord.y;
      if (y < 0 || y >= scale) return null;

      return 'https://developers.google.com/maps/documentation/' +
             'javascript/examples/full/images/gall-peters_' + zoom +
             '_' + x + '_' + y + '.png';
    },
    tileSize: new google.maps.Size(GALL_PETERS_RANGE_X, GALL_PETERS_RANGE_Y),
    isPng: true,
    minZoom: 0,
    maxZoom: 1,
    name: 'Gall-Peters'
  });

  // Describe the Gall-Peters projection used by these tiles.
  gallPetersMapType.projection = {
    fromLatLngToPoint: function(latLng) {
      var latRadians = latLng.lat() * Math.PI / 180;
      return new google.maps.Point(
          GALL_PETERS_RANGE_X * (0.5 + latLng.lng() / 360),
          GALL_PETERS_RANGE_Y * (0.5 - 0.5 * Math.sin(latRadians)));
    },
    fromPointToLatLng: function(point, noWrap) {
      var x = point.x / GALL_PETERS_RANGE_X;
      var y = Math.max(0, Math.min(1, point.y / GALL_PETERS_RANGE_Y));

      return new google.maps.LatLng(
          Math.asin(1 - 2 * y) * 180 / Math.PI,
          -180 + 360 * x,
          noWrap);
    }
  };
}

// GeoJSON, describing the locations and names of some cities.
var cities = {
  type: 'FeatureCollection',
  features: [{
    type: 'Feature',
    geometry: {type: 'Point', coordinates: [-87.650, 41.850]},
    properties: {name: 'Chicago'}
  }, {
    type: 'Feature',
    geometry: {type: 'Point', coordinates: [-149.900, 61.218]},
    properties: {name: 'Anchorage'}
  }, {
    type: 'Feature',
    geometry: {type: 'Point', coordinates: [-99.127, 19.427]},
    properties: {name: 'Mexico City'}
  }, {
    type: 'Feature',
    geometry: {type: 'Point', coordinates: [-0.126, 51.500]},
    properties: {name: 'London'}
  }, {
    type: 'Feature',
    geometry: {type: 'Point', coordinates: [28.045, -26.201]},
    properties: {name: 'Johannesburg'}
  }, {
    type: 'Feature',
    geometry: {type: 'Point', coordinates: [15.322, -4.325]},
    properties: {name: 'Kinshasa'}
  }, {
    type: 'Feature',
    geometry: {type: 'Point', coordinates: [151.207, -33.867]},
    properties: {name: 'Sydney'}
  }, {
    type: 'Feature',
    geometry: {type: 'Point', coordinates: [0, 0]},
    properties: {name: '0°N 0°E'}
  }]
};
<div id="map"></div>
<div id="coords"></div>
#coords {
  background-color: black;
  color: white;
  padding: 5px;
}
<!-- Replace the value of the key parameter with your own API key. -->
<script async defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap"></script>
// This example defines an image map type using the Gall-Peters
// projection.
// https://en.wikipedia.org/wiki/Gall%E2%80%93Peters_projection

function initMap() {
  // Create a map. Use the Gall-Peters map type.
  var map = new google.maps.Map(document.getElementById('map'), {
    zoom: 0,
    center: {lat: 0, lng: 0},
    mapTypeControl: false
  });

  initGallPeters();
  map.mapTypes.set('gallPeters', gallPetersMapType);
  map.setMapTypeId('gallPeters');

  // Show the lat and lng under the mouse cursor.
  var coordsDiv = document.getElementById('coords');
  map.controls[google.maps.ControlPosition.TOP_CENTER].push(coordsDiv);
  map.addListener('mousemove', function(event) {
    coordsDiv.textContent =
        'lat: ' + Math.round(event.latLng.lat()) + ', ' +
        'lng: ' + Math.round(event.latLng.lng());
  });

  // Add some markers to the map.
  map.data.setStyle(function(feature) {
    return {
      title: feature.getProperty('name'),
      optimized: false
    };
  });
  map.data.addGeoJson(cities);
}

var gallPetersMapType;
function initGallPeters() {
  var GALL_PETERS_RANGE_X = 800;
  var GALL_PETERS_RANGE_Y = 512;

  // Fetch Gall-Peters tiles stored locally on our server.
  gallPetersMapType = new google.maps.ImageMapType({
    getTileUrl: function(coord, zoom) {
      var scale = 1 << zoom;

      // Wrap tiles horizontally.
      var x = ((coord.x % scale) + scale) % scale;

      // Don't wrap tiles vertically.
      var y = coord.y;
      if (y < 0 || y >= scale) return null;

      return 'https://developers.google.com/maps/documentation/' +
             'javascript/examples/full/images/gall-peters_' + zoom +
             '_' + x + '_' + y + '.png';
    },
    tileSize: new google.maps.Size(GALL_PETERS_RANGE_X, GALL_PETERS_RANGE_Y),
    isPng: true,
    minZoom: 0,
    maxZoom: 1,
    name: 'Gall-Peters'
  });

  // Describe the Gall-Peters projection used by these tiles.
  gallPetersMapType.projection = {
    fromLatLngToPoint: function(latLng) {
      var latRadians = latLng.lat() * Math.PI / 180;
      return new google.maps.Point(
          GALL_PETERS_RANGE_X * (0.5 + latLng.lng() / 360),
          GALL_PETERS_RANGE_Y * (0.5 - 0.5 * Math.sin(latRadians)));
    },
    fromPointToLatLng: function(point, noWrap) {
      var x = point.x / GALL_PETERS_RANGE_X;
      var y = Math.max(0, Math.min(1, point.y / GALL_PETERS_RANGE_Y));

      return new google.maps.LatLng(
          Math.asin(1 - 2 * y) * 180 / Math.PI,
          -180 + 360 * x,
          noWrap);
    }
  };
}

// GeoJSON, describing the locations and names of some cities.
var cities = {
  type: 'FeatureCollection',
  features: [{
    type: 'Feature',
    geometry: {type: 'Point', coordinates: [-87.650, 41.850]},
    properties: {name: 'Chicago'}
  }, {
    type: 'Feature',
    geometry: {type: 'Point', coordinates: [-149.900, 61.218]},
    properties: {name: 'Anchorage'}
  }, {
    type: 'Feature',
    geometry: {type: 'Point', coordinates: [-99.127, 19.427]},
    properties: {name: 'Mexico City'}
  }, {
    type: 'Feature',
    geometry: {type: 'Point', coordinates: [-0.126, 51.500]},
    properties: {name: 'London'}
  }, {
    type: 'Feature',
    geometry: {type: 'Point', coordinates: [28.045, -26.201]},
    properties: {name: 'Johannesburg'}
  }, {
    type: 'Feature',
    geometry: {type: 'Point', coordinates: [15.322, -4.325]},
    properties: {name: 'Kinshasa'}
  }, {
    type: 'Feature',
    geometry: {type: 'Point', coordinates: [151.207, -33.867]},
    properties: {name: 'Sydney'}
  }, {
    type: 'Feature',
    geometry: {type: 'Point', coordinates: [0, 0]},
    properties: {name: '0°N 0°E'}
  }]
};

Ver o exemplo (map-projection-simple.html).

Enviar comentários sobre…

Google Maps JavaScript API
Google Maps JavaScript API
Precisa de ajuda? Acesse nossa página de suporte.