Estrutura do projeto
Para este exercício, nossa demonstração personalizada do Google Maps ficará no GitHub (não no CodePen). Aqui está o estrutura do projeto:
map/ ├── index.html ├── img/ │ ├── address.svg │ ├── modal-fax.svg │ ├── modal-lat-long.svg │ ├── modal-pin.svg │ ├── modal-tel.svg │ └── pin.svg ├── main.css └── main.js
1. Montando o projeto
Antes de começarmos a criar nosso projeto (que vai se parecer com um mini app) existem algumas coisas que devemos levar em consideração.
Pegue uma chave de API do Google Maps
Como primeira e obrigatória, devemos obter uma chave de API do Google Maps. Para fazer isso, precisamos seguir estas instruções e configurar um projeto no Console do Google Cloud com o API JavaScript do Google Maps ativado.
Para esta demonstração, pegaremos emprestada uma chave de API de uma série antiga, mas ainda popular, chamada A API do Google Maps para designers. Há também uma demonstração associada de onde podemos extrair a API.
aviso
Esta chave de API de demonstração tem limites de uso! Certifique-se de registrar sua própria chave de API e substituir a do exemplo.
Por último, mas não menos importante, assim que você configurar esse projeto no Console do Google Cloud, é sempre aconselhável restringir a API associada. Por exemplo, você pode ter um único projeto e uma API que você compartilha com todos os clientes do seu site. Nesse caso, você pode restringir as solicitações de API a sites específicos.
Pegue alguns dados
Para criar os marcadores e tornar nosso projeto o mais realista possível, precisaremos de alguns dados do mundo real. Com isso em mente, como mencionado anteriormente, pegaremos 13 dos escritórios da Adobe e os fixaremos em nosso mapa.
Como veremos mais adiante, cada local precisa incluir sua latitude e longitude. Como essas informações não estão disponíveis na página de contato da Adobe, usaremos o LangLong.net site para recuperar suas coordenadas. Algumas das coordenadas podem não ser perfeitamente precisas, mas você entendeu.
Pegue alguns ícones
Para melhorar a aparência da demonstração, precisaremos de alguns ícones.
O Envato Elements fornece centenas de ícones de mapas e navegação diferentes para nossas necessidades. Nesse caso, usaremos um conjunto de ícones que segue um estilo de linha preenchida. Como vimos na estrutura do projeto, os ícones SVG selecionados ficarão dentro do img
pasta.
Aqui estão os ícones SVG que usaremos em nosso projeto:
Incluir Arquivos de Bootstrap
Por último, embora não seja obrigatório, para acelerar o processo de desenvolvimento também incluiremos o Bootstrap em nosso projeto seguindo a abordagem CDN, conforme descrito nesta página.
2. Definir a marcação da página
Agora que temos tudo configurado, vamos olhar para a nossa marcação.
Arquivos necessários
Abaixo você pode ver a marcação inicial com todos os arquivos Bootstrap necessários, nossos arquivos e o script
tag para a API JavaScript do Google Maps:
A simple example showing how to build a stylish Google Map with multiple markers
Basta dar uma olhada no script
tag para a API JavaScript do Google Maps. Você verá dois atributos:
- o
src
O atributo inclui a chamada base para a API JavaScript do Google Maps junto com três parâmetros: dois obrigatórios e um opcional. O necessáriokey
O parâmetro armazena nossa chave de API conforme recuperada do Console do Google Cloud. O opcionallanguage
O parâmetro determina o idioma do mapa (nomes de locais, rótulos, etc.). O necessáriocallback
O parâmetro define o nome da função global que será acionada assim que a API JavaScript do Google Maps terminar seu carregamento. - o
async
O parâmetro informa ao navegador para baixar e executar o script de forma assíncrona.
Layout personalizado do Google Maps
Antes de dar uma olhada nos elementos da página, vamos discutir os requisitos de layout.
- Em telas de celular (<768px), o layout será assim:
- Em telas médias e grandes (≥768px), haverá duas colunas de largura igual:
- Em cada caso, o mapa cobrirá a altura da janela.
Aqui está a marcação associada preenchida com classes auxiliares do Bootstrap:
Some of Adobe's office locations
North America
Corporate headquartersLos Angeles
Mais importante, observe duas coisas:
- Cada link de local, que representa um local da Adobe, vem com o
data-index
atributo. Lembre-se desse atributo, pois o usaremos mais tarde. - Há um elemento vazio com o
map
EU IRIA. Isso incluirá o conteúdo do mapa e será gerado por meio de JavaScript.
3. Adicione o JavaScript
Neste ponto, estamos prontos para criar a funcionalidade principal do nosso projeto personalizado do Google Maps. Vamos fazer isso!
Locais de lojas
Capturamos os locais na marcação, mas também precisamos deles em JavaScript. Então, vamos armazená-los em um array como este:
const pins = [ { location: "North America", name: "Corporate headquarters", address: "345 Park Avenue
San Jose, CA 95110-2704", tel: "408-536-2800", fax: "408-537-6000", lat: 37.33078, long: -121.892357, }, { location: "North America", name: "Los Angeles", address: "(former Magento office)
3640 Holdrege Ave
Los Angeles, CA 90016", lat: 34.01989, long: -118.37811, }, // more locations here ];
Lembre-se de que preservamos a ordem em que os locais aparecem na marcação e no objeto. Um local com data-index="0"
na marcação denota que o mesmo local deve estar no primeiro lugar do pins
variedade.
Observação: em um cenário do mundo real, provavelmente haveria uma linguagem de back-end para gerenciar todos os locais em um só lugar. Por exemplo, se você estiver familiarizado com o WordPress e o plugin ACF PRO, provavelmente terá um conteúdo flexível ou um campo repetidor onde colocará todos os locais. Dentro dele, haverá campos extras para gerenciar os detalhes do local. Especialmente para pegar as coordenadas de cada local, você pode ter um campo do Google Maps. Em seguida, através do wp_localize_script()
você pode passar as localizações no JavaScript e construir um objeto semelhante ao que temos aqui.
Inicialize o mapa personalizado do Google
A seguir, inicializaremos o mapa através do initMap()
que mostramos antes.
Nosso mapa terá as seguintes personalizações:
- Será centrado em Londres, Reino Unido.
- Vai ter
zoom: 3
para ver o maior número possível de locais por padrão. - Vamos personalizar seus estilos padrão através desta ferramenta, mas você sempre pode optar por cestilo de mapa baseado em alto volume. Mais notavelmente, mudaremos a cor padrão da água assim:
Com todos os itens acima em mente, aqui está o corpo inicial da nossa função:
// London, UK const center = { lat: 51.507351, lng: -0.127758 }; const styles = [ { featureType: "poi", stylers: [ { visibility: "off" } ] }, { featureType: "water", stylers: [ { color: "#39C3FC" } ] } ]; function initMap() { const map = new google.maps.Map(document.getElementById("map"), { center, styles, zoom: 3 }); }
Criar marcadores do Google Maps
Dentro de initMap()
função, também chamaremos a createMarkers()
função para criar os marcadores de localização:
function initMap() { // map declaration here createMarkers(map); }
Dentro desta função, faremos o seguinte:
- Inicialize uma janela de informações que exibirá informações sobre um marcador sempre que alguém clicar nele.
- Substitua o ícone do marcador padrão por um SVG personalizado.
- Percorra os locais e posicione-os no mapa com base em suas coordenadas. Além disso, faça-os aparecer com uma animação DROP.
- Armazene cada instância do marcador no
markers
variedade. Veremos porque mais tarde.
Segue a declaração da função:
function createMarkers(map) { const infowindow = new google.maps.InfoWindow(); const markerIcon = { url: "img/pin.svg", scaledSize: new google.maps.Size(40, 40) }; for (let i = 0; i < pins.length; i++) { const marker = new google.maps.Marker({ position: { lat: pins[i].lat, lng: pins[i].long }, map, icon: markerIcon, animation: google.maps.Animation.DROP }); markers.push(marker); } }
Alternar janela de informações
Dentro de createMarkers()
função, também registraremos um click
evento para cada marcador.
function createMarkers(map) { ... for (let i = 0; i < pins.length; i++) { // marker here google.maps.event.addListener(marker, "click", function () { infowindow.setContent(createInfoWindowContent(pins[i])); map.setCenter(marker.getPosition()); infowindow.open(map, marker); const targetLocation = document.querySelector(`[data-index="${i}"]`); if (document.querySelector(".location.active")) { document .querySelector(".location.active") .classList.remove(activeClass); } targetLocation.classList.add(activeClass); scroll({ top: targetLocation.offsetTop, behavior: "smooth" }); }); } }
Cada vez que um usuário clicar em um marcador, realizaremos as seguintes ações:
- Preencha o conteúdo da janela de informações com conteúdos associados a este marcador graças ao
createInfoContent()
função. - Defina o centro do mapa com base nas coordenadas deste marcador.
- Mostrar a janela de informações.
- Remova o
active
classe de qualquer link de local associado, se houver. - Encontre o link de localização cujo índice corresponda ao índice desse marcador e dê a ele o
active
classe. Isso dará ao link de destino uma cor de fundo azul.
- Desloque suavemente para o link de localização correspondente.
Preencher Janela de Informações
Como dissemos, o trabalho do createInfoContent()
função será alimentar a janela de informações com o conteúdo do marcador clicado.
Usaremos marcação direta para exibir o conteúdo de cada marcador. Dado que alguns locais nem sempre têm todos os detalhes, aplicaremos algumas verificações para garantir que nossa marcação não fique inchada.
Segue a declaração da função:
function createInfoWindowContent(pin) { let phoneString = ""; let faxString = ""; let latLongString = ""; let addressString = ""; if (pin.tel) { phoneString = `${pin.tel}
`; } if (pin.fax) { faxString = `${pin.fax}
`; } if (pin.lat && pin.long) { latLongString = `${pin.lat}, ${pin.long}
`; } if (pin.address) { addressString = `${pin.address}`; } const contentString = `${pin.name}
${phoneString} ${faxString} ${latLongString} ${addressString} `; return contentString; }
Links de localização
Discutimos o que deve acontecer quando um marcador é clicado. Mas também precisamos aplicar alguma funcionalidade quando acontece o contrário. Em outras palavras, queremos garantir que cada vez que um usuário clicar em um link de local, o marcador correspondente seja clicado.
Outra função, a showLocations()
one, será responsável por lidar com essa funcionalidade. Este também viverá dentro do initMap()
função.
Assim, sempre que um link de local for clicado, realizaremos as seguintes ações:
- Cancele seu comportamento padrão.
- Remova o
active
classe de qualquer link de local, se houver. - Adicione o
active
classe para este link. - Rolagem suave para o mapa.
- Encontre o marcador cujo índice corresponde ao índice deste link e acione seu
click
evento. Podemos segmentar o marcador especificado porque o armazenamos em uma etapa anterior dentro domarkers
variedade.
Aqui está a definição da função:
function showLocations() { const locations = document.querySelectorAll(".location"); locations.forEach((location) => { location.addEventListener("click", function (e) { e.preventDefault(); if (document.querySelector(".location.active")) { document .querySelector(".location.active") .classList.remove(activeClass); } location.classList.add(activeClass); scroll({ top: document.getElementById("map").offsetTop, behavior: "smooth" }); new google.maps.event.trigger(markers[this.dataset.index], "click"); }); }); }
Conclusão
E terminamos! Essa foi uma jornada bastante longa, mas espero que você tenha gostado e que tenha ajudado a aprimorar suas habilidades em relação à API JavaScript do Google Maps.
Mais uma vez, não se esqueça de colocar sua própria chave para testar o projeto ao vivo! Segue o link do projeto.
As coisas não param por aqui. Podemos continuar aprimorando/estendendo este projeto fazendo várias coisas, por exemplo:
- Coloque em grupos de marcadores de tabela para agrupar marcadores. Esta é uma boa adição, especialmente para casos onde há muitos marcadores.
- Torne este projeto dinâmico usando WordPress e ACF PRO, conforme explicado em algumas seções acima. Dependendo de como for esse projeto, provavelmente voltarei com um tutorial desse tipo no futuro 🙂
- Restrinja os limites do mapa para evitar mostrar uma área cinza ao arrastar ou diminuir o zoom.
Como sempre, muito obrigado por ler!