Os mapas se tornaram parte integrante de nossa vida cotidiana. Desde dirigir até um local até encontrar alguns restaurantes ou lojas nas proximidades ou durante o planejamento de viagens, quase todo tipo de aplicativo usa mapas. O uso de mapas nos ajuda a adicionar serviços baseados em localização em nosso aplicativo.

Uma maneira de adicionar mapas em um aplicativo da web é usando o Leaflet JS. Leaflet JS é uma biblioteca JavaScript de código aberto para adicionar mapas da web simples e interativos. Ele pode adicionar os dados do mapa às camadas do mapa e possui recursos como panorâmica, zoom, etc. que a maioria dos aplicativos exige. Embora o folheto forneça alguns recursos básicos necessários em qualquer aplicativo de mapa, uma maneira fácil de aumentar a funcionalidade dos mapas é usar plug-ins de terceiros. Como o folheto é uma biblioteca de código aberto, ou seja, seu código-fonte está disponível no GitHub, houve muitas contribuições e muitos plug-ins disponíveis. Você pode obter a lista dos plug-ins aqui .

Portanto, o Leaflet é uma API de mapa e nos ajuda a interagir com os dados do mapa, mas não está fornecendo nenhum dado. Nem fornece o mapa em si, pois não é um serviço de mapeamento. Então, como obtemos o mapa? A resposta é que o folheto depende de terceiros para fornecer o mapa base, ou seja, o folheto é construído de forma que possa ser usado com várias camadas de mapa base. Geralmente, o Leaflet é usado com OpenStreetMaps, mas podemos até usar outros provedores de mapa como Mapbox, Ersi, Bing Map Layers, etc. Você pode verificar diferentes provedores de mapa base aqui .

Então, vamos entender como o folheto pode ser usado para interagir com os mapas passo a passo:

1. A Estrutura do Diretório

Esta é a estrutura de diretório que será seguida durante este exemplo. Você também pode ter uma estrutura de diretório diferente, mas certifique-se de que ela se reflita em seu código também.

2. HTML Boilerplate e adição de referências de folheto

<!DOCTYPE html>
<html>
  
<head>
    <title> Playing Around With Leaflet JS </title>
    <meta charset="UTF-8">
    <meta name="viewport" content=
        "width=device-width, initial-scale=1.0">
  
    <!-- Leaflet CSS -->
    <link rel="stylesheet" href=
"https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"
        integrity=
"sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A=="
        crossorigin="" />
  
    <!-- Leaflet JS -->
    <script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"
        integrity=
"sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA=="
        crossorigin=""></script>
</head>
  
<body></body>
  
</html>

Para adicionar um mapa à nossa página da web, são necessárias tecnologias simples da web, como HTML, CSS e JavaScript. Para usar o Leaflet em seu código, você precisa adicionar o Leaflet CSS e o Leaflet JS. Você pode baixá- los ou usá-los incluindo seus CDNs (veja o exemplo de código acima).

3. Crie um recipiente de mapa e crie um objeto de mapa

<div id="mymap"> </div>

Primeiro definimos um elemento de contêiner onde queremos carregar o mapa e fornecer a ele um id “mymap”.

let map = L.map('mymap').setView([19.5937, 78.9629], 5);

Agora, criamos um objeto de mapa usando o qual criaremos um mapa e o manipularemos. Instanciamos o objeto de mapa com o id do elemento de contêiner criado acima, ou seja, “mymap”. O método setview é usado para definir o centro do mapa e o nível de zoom.

4. Adicionar blocos de mapa usando TileLayer

L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    attribution: '© OpenStreetMap contributors',
    maxZoom: 20,
    minZoom: 2,
    tileSize: 512,
    zoomOffset: -1
}).addTo(map);

Para carregar e exibir nosso mapa, usamos a classe TileLayer para criar uma camada e especificar a URL dos blocos do mapa. O mapa é dividido em vários blocos e estamos usando o OpenStreetMap para exibir os blocos do mapa. Você pode obter a lista de fornecedores de peças aqui. Especificamos alguns parâmetros adicionais, como nível mínimo de zoom, nível máximo de zoom e tamanho do bloco. Como estamos usando os blocos de mapas do OpenStreetMap, precisamos fornecer a atribuição adequada (ou créditos) ao OpenStreetMap (ou qualquer provedor de blocos de mapas que você esteja usando) para usar seus blocos de mapas. Para adicionar essa camada em nosso mapa, usamos o método addTo(). 

5. Fazendo nosso conjunto de dados para incluir marcadores

https://github.com/OptimalLearner/Leaflet-JS-Example-Code/blob/master/assets/location-data.json

Agora, precisamos adicionar alguns marcadores ao mapa que apontam para algum local. Salvamos os dados em um arquivo diferente denominado “location-data.json”. Este arquivo contém os detalhes do marcador, como coordenadas de latitude e longitude, etc. Você pode acessar os dados do link acima fornecido e salvá-los junto com seu código. Se você deseja manter os dados em seu próprio arquivo JS, pode criar uma variável e atribuí-la aos dados acima.

6. Criação de marcador, popups de ligação e manipulação de eventos

let marker = L.marker([latitude, longitude]).bindPopup(`<h3> ${title} </h3> 
<p> ${description} </p>
`).on('click', () => {
    map.flyTo([latitude, longitude], zoomLevel);
}).addTo(map);

Um marcador é usado para identificar e destacar um local no mapa. Para adicionar um marcador no folheto, inicializamos a classe do marcador e passamos as coordenadas do local para o qual precisamos que o marcador aponte. Você pode adicionar quantos marcadores desejar. Agora, para identificar qual local está marcado pelo marcador, podemos adicionar um pop-up ao marcador que nos dirá as informações do local. Adicionamos um pop-up usando o método bindPopup para exibir o nome do local e uma pequena descrição do local.

O folheto também tem a capacidade de reagir aos eventos gerados por nós. Podemos adicionar um ouvinte de evento usando a função “on” para um evento particular (em nosso caso “clique”) que escuta uma função contendo algum conjunto de operações. No final, adicionamos este marcador ao nosso mapa.

7. Personalização do ícone do marcador

let iconOption = {
    iconUrl: './assets/location-marker.svg',
    iconSize: [30, 30]
};
let ourCustomIcon = L.icon(iconOption);
  
let marker = L.marker([latitude, longitude], 
  {icon: ourCustomIcon}).bindPopup(`<h3> ${title} </h3> 
<p> ${description} </p>
`).on('click', () => {
    map.flyTo([latitude, longitude], zoomLevel);
}).addTo(map);

Nem todo mundo gostaria de usar o mesmo ícone de marcador padrão. Então, aqui vem o recurso de ícones de marcadores personalizados para o resgate. Você precisa usar a classe Icon e passar a URL do ícone que deseja usar como marcador e adicionar o tamanho do ícone [largura, altura] em pixels (px). Agora precisamos adicionar o ícone ao marcador. Na classe Marker, depois de adicionar as coordenadas, podemos passar o ícone do marcador personalizado para renderizar o marcador.

8. O que é melhor para você: flyTo ou setView?

map.setView([latitude, longitude], zoomLevel);
map.flyTo([latitude, longitude], zoomLevel);

Ambos estão fazendo o mesmo trabalho de alterar o local para coordenadas específicas, mas o método flyTo() fornece algumas animações que voarão para o local especificado usando coordenadas. Se precisar de alguma animação, você pode usar o método flyTo(), senão setView() também funciona para alterar o local.

Existe outro método chamado panTo ([latitude, longitude]) que está apenas chamando setView() mantendo o nível de zoom no nível de zoom do mapa atual. O método setView() permite até mesmo definir o nível de zoom, mas esse não é o caso com panTo().

9. Código Completo e Resultado

<!DOCTYPE html>
<html>
  
<head>
    <title> Playing Around With LeafletJS </title>
    <meta charset="UTF-8">
    <meta name="viewport" content=
        "width=device-width, initial-scale=1.0">
          
    <!-- Leaflet CSS -->
    <link rel="stylesheet" href=
        "https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"
        integrity=
"sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A=="
        crossorigin="" />
  
    <!-- Leaflet JS -->
    <script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"
        integrity=
"sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA=="
        crossorigin=""></script>
          
    <!-- Custom Styles -->
    <link rel="stylesheet" type="text/css" href="css/styles.css">
</head>
  
<body>
    <h2 class="heading"> Some Indian Monuments </h2>
    <div id="mymap"> </div>
    <div class="button-group flex-style">
        <div class="component1">
            <button class="map-zoom-out-btn">Map Zoom Out</button>
        </div>
        <div class="component2">
            <select class="select-dropdown" name="dropdown">
                <option> Select any monument </option>
            </select>
            <button class="search-btn"> Search </button>
        </div>
    </div>
    <footer class="footer flex-style"> Made Using Leaflet JS | 
        <a href=
"https://github.com/OptimalLearner/Leaflet-JS-Example-Code" 
            target="_blank"> Source Code</a> <a href=""
            target="_blank"> <img src="assets/github-icon.png" /> 
        </a> 
    </footer>
  
    <script type="text/javascript" src="js/script.js"></script>
</body>
  
</html>
body {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    font-family: sans-serif;
}
.heading {
    font-family: monospace;
    font-size: 40px;
    text-align: center;
    margin: 2.5vh 0;
}
#mymap {
    width: 90vw;
    height: 70vh;
    margin: 0 5vw 2vh;
    border: 3px solid #888;
}
.button-group {
    justify-content: space-evenly !important;
}
.map-zoom-out-btn, .search-btn {
    background-color: #0072B5;
    color: #FFF;
    padding: 10px 35px;
    border: none;
    font-size: 17px;
    border-radius: 5px;
    cursor: pointer;
}
.select-dropdown {
    display: inline-block;
    margin: 0 15px 0 0;
    padding: 10px 35px;
    border: 1px solid #AAA;
    font: inherit;
    -webkit-appearance: none;
    -moz-appearance: none;
    -ms-appearance: none;
    appearance: none;
    background: #FFF;
    background-repeat: no-repeat;
    background-image: 
        linear-gradient(45deg, transparent 50%, currentColor 50%), 
        linear-gradient(135deg, currentColor 50%, transparent 50%);
    background-position: right 15px top 1em, right 10px top 1em;
    background-size: 5px 5px, 5px 5px;
}
.footer {
    position: fixed;
    left: 0;
    bottom: 0;
    width: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
    text-align: center;
    font-size: 17px;
    padding-bottom: 8px;
}
.footer a {
    padding: 0 5px 0 5px;
    color: #000;
    cursor: pointer;
}
.flex-style {
    display: flex;
    justify-content: center;
    align-items: center;
}
let map = L.map("mymap").setView([19.5937, 78.9629], 5);
let ourData = [];
  
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
  attribution: "© OpenStreetMap contributors",
  maxZoom: 20,
  minZoom: 2,
  tileSize: 512,
  zoomOffset: -1,
}).addTo(map);
  
let iconOption = {
  iconUrl: "./assets/location-marker.svg",
  iconSize: [30, 30],
};
let ourCustomIcon = L.icon(iconOption);
  
fetch("./assets/location-data.json")
  .then((response) => response.json())
  .then((data) => {
    ourData = data;
    for (let i = 0; i < data.length; i++) {
      let option = document.createElement("option");
      option.value = i + 1;
      option.text = data[i].title;
      document.querySelector(".select-dropdown").appendChild(option);
  
      let marker = L.marker([data[i].latitude, data[i].longitude], {
        icon: ourCustomIcon,
      })
        .bindPopup(
          `<h3> ${data[i].title} </h3> 
<p> ${data[i].description} </p>
`
        )
        .on("click", () => {
          map.flyTo([data[i].latitude, data[i].longitude], data[i].zoomLevel);
        })
        .addTo(map);
    }
  })
  .catch((error) => alert(error));
  
document.querySelector(".map-zoom-out-btn").addEventListener("click", () => {
  map.flyTo([19.5937, 78.9629], 5);
});
  
document.querySelector(".search-btn").addEventListener("click", () => {
  let select = document.querySelector(".select-dropdown");
  let value = select.options[select.selectedIndex].value;
  map.flyTo(
    [ourData[value - 1].latitude, ourData[value - 1].longitude],
    ourData[value - 1].zoomLevel
  );
});

Usando o HTML Boilerplate, adicionamos um contêiner de mapa, um botão para diminuir o zoom do mapa e um menu suspenso que conterá os locais marcados no mapa. Aplicamos alguns estilos aos nossos componentes usando CSS externo, adicionando referências à folha de estilo externa. No arquivo de script, criamos um objeto de mapa e adicionamos blocos de mapa ao objeto. Em seguida, criamos nosso objeto de ícone personalizado e adicionamos o tamanho e a URL do ícone às opções de ícone que adicionaremos ao marcador ao criar o marcador para cada local.

Usando a API Fetch, solicitamos nossos dados fornecendo a URL dos dados. Obtemos o objeto de resposta que é então convertido para json. Usando esses dados json que contêm as informações sobre os locais, adicionamos dinamicamente as opções para os locais à lista suspensa usando DOM e criamos marcadores para cada local junto com pop-ups e ouvinte de evento onclick. Em caso de erros, a mensagem de erro é alertada ao usuário.

Adicionamos um ouvinte de evento onclick no botão Zoom Out que nos leva às coordenadas iniciais e ao nível de zoom. Também adicionamos um ouvinte de evento no botão Pesquisar que obtém o valor da lista suspensa e, usando o valor, selecionamos o local e ampliamos o mapa para aquele local selecionado.

O resultado do exemplo acima pode ser visto abaixo:

Para executar sua página da web localmente, você precisa executá-la por meio do servidor local. Você pode usar WAMP ou XAMPP ou simpleNode.js http-server. Se você ficar preso em algum ponto intermediário, pode consultar este Repositório GitHub .