JavaScript en 60 secondes: Travailler avec une carte (API de géolocalisation, Leaflet.js, Nominatim)





Bonne journée, mes amis!



Dans ce petit tutoriel, nous effectuerons trois tâches simples avec vous:



  • À l'aide de l'API de géolocalisation et de Leaflet.js, déterminez l'emplacement actuel de l'utilisateur et affichez-le sur la carte
  • Nous mettons en œuvre une transition animée entre les villes
  • Nous implémentons la commutation entre les adresses avec l'obtention préalable du nom de l'objet et de ses coordonnées


Le code du projet est ici .



Vous pouvez jouer avec le code ici:







Déterminer l'emplacement actuel de l'utilisateur



L'API de géolocalisation permet à un utilisateur de fournir à une application Web ses données de localisation. L'application utilise la méthode Geolocation.getCurrentPosition () pour demander ces données . Cette méthode prend un paramètre obligatoire et deux paramètres facultatifs: succès est une fonction de rappel qui reçoit un objet Position lorsque l'autorisation est accordée, error est une fonction de rappel qui reçoit un objet PositionError lorsque l'accès est refusé et options est un objet de paramètres. Voici à quoi cela ressemble dans le code:



navigator.geolocation.getCurrentPosition(success, error, {
  //  
  enableHighAccuracy: true
})

function success({ coords }) {
  //    
  const { latitude, longitude } = coords
  const position = [latitude, longitude]
  console.log(position) // [, ]
}

function error({ message }) {
  console.log(message) //      PositionError: User denied Geolocation
}

      
      





Afficher la position de l'utilisateur sur la carte



Nous utiliserons Leaflet.js comme carte . Ce service est une alternative à Google Maps et OpenStreetMap, inférieure à eux en fonctionnalité, mais captivante par la simplicité de l'interface. Nous créons un balisage dans lequel nous connectons les styles et le script de carte:



<head>
  <!--   -->
  <link
      rel="stylesheet"
      href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"
      integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A=="
      crossorigin=""
    />
    <!--   -->
    <script
      src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"
      integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA=="
      crossorigin=""
    ></script>
    <!--   -->
    <link rel="stylesheet" href="style.css" />
</head>
<body>
  <!--    -->
  <div id="map"></div>
  <!--     -->
  <button id="my_position">My Position</button>
  <!--  - -->
  <script src="script.js" type="module"></script>
</body>

      
      





Ajoutez des styles minimaux (style.css):



* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  min-height: 100vh;
  display: grid;
  place-content: center;
  place-items: center;
  background-color: rgb(241, 241, 241);
}

#map {
  width: 480px;
  height: 320px;
  border-radius: 4px;
  box-shadow: 0 0 1px #222;
}

button {
  padding: 0.25em 0.75em;
  margin: 1em 0.5em;
  cursor: pointer;
  user-select: none;
}

      
      





Créez un module map.js avec le contenu suivant:



//       
//      
let map = null
let marker = null

//    -     
//  ,    (tooltip)
export function getMap(position, tooltip) {
  //     
  if (map === null) {
    //  ,   setView -   (zoom)
    map = L.map('map').setView(position, 15)
  } else return

  // -  
  //      
  L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    attribution:
      '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
  }).addTo(map)

  //    
  L.marker(position).addTo(map).bindPopup(tooltip).openPopup()
}

      
      





Enfin, nous créons script.js:



//  
import { getMap } from './map.js'

//       
document.getElementById('my_position').onclick = () => {
  navigator.geolocation.getCurrentPosition(success, error, {
    enableHighAccuracy: true
  })
}

function success({ coords }) {
  const { latitude, longitude } = coords
  const currentPosition = [latitude, longitude]
  //  ,      
  getMap(currentPosition, 'You are here')
}

function error({ message }) {
  console.log(message)
}

      
      





Ouvrez index.html dans un navigateur, cliquez sur le bouton, accordez la permission de recevoir des données de localisation, consultez notre position sur la carte.







Bien. Passer à autre chose.



Transition animée entre les villes



Supposons que nous ayons un objet avec trois villes (Moscou, Saint-Pétersbourg, Ekaterinbourg) et leurs coordonnées (db / cities.json):



{
  "Moscow": {
    "lat": "55.7522200",
    "lon": "37.6155600"
  },
  "Saint-Petersburg": {
    "lat": "59.9386300",
    "lon": "30.3141300"
  },
  "Ekaterinburg": {
    "lat": "56.8519000",
    "lon": "60.6122000"
  }
}

      
      





Nous devons mettre en œuvre une commutation fluide entre ces villes sur la carte.



Ajoutez un conteneur pour les villes au balisage:



<div id="cities"></div>

      
      





Réécriture de script.js:



import { getMap } from './map.js'

//    
const $cities = document.getElementById('cities')

;(async () => {
  //    
  const response = await fetch('./db/cities.json')
  const cities = await response.json()
  //  
  for (const city in cities) {
    //  
    const $button = document.createElement('button')

    //    -  
    $button.textContent = city

    //    
    const { lat, lon } = cities[city]

    //   ,   
    //   data-
    $button.dataset.city = city
    $button.dataset.lat = lat
    $button.dataset.lon = lon

    //    
    $cities.append($button)
  }
})()

//   
$cities.addEventListener('click', ({ target }) => {
  //     
  if (target.tagName !== 'BUTTON') return

  //   ,     data-
  const { city, lat, lon } = target.dataset
  const position = [lat, lon]
  //  ,      
  getMap(position, city)
})

      
      





Changeons aussi un peu map.js:



let map = null
let marker = null

export function getMap(position, tooltip) {
  if (map === null) {
    map = L.map('map').setView(position, 15)
  } else {
    //    
    map.flyTo(position)
  }

  L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    attribution:
      '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
  }).addTo(map)

  //   
  if (marker) {
    map.removeLayer(marker)
  }
  marker = new L.Marker(position).addTo(map).bindPopup(tooltip).openPopup()
}

      
      





Ouvrez index.html. Lorsque vous appuyez sur le premier bouton, nous obtenons immédiatement la position et le nom de la ville. Lorsque vous appuyez sur le deuxième bouton et les suivants, nous nous déplaçons en douceur entre les villes.







Commutation fluide entre les adresses



Supposons que nous ayons trois objets avec des noms et des adresses (db / addresses.json):



{
  " ": " , 2",
  "   ": " , 46",
  "-": " , 97"
}

      
      





Nous devons implémenter la commutation entre ces objets sur la carte. Mais comment pouvons-nous faire cela sans coordonnées? En aucune façon. Par conséquent, nous devons en quelque sorte obtenir ces coordonnées. Pour ce faire, nous utiliserons le service Nominatim d'OpenStreetMap. Pour plus d'informations sur la manière de former correctement une chaîne de requête, cliquez ici . Je ne montrerai qu'une des options possibles.



Donc, nous créons un conteneur pour les adresses dans le balisage:



<div id="addresses"></div>

      
      





Réécriture de script.js:



//    
const $addresses = document.getElementById('addresses')

;(async () => {
  //    
  const response = await fetch('./db/addresses.json')
  const addresses = await response.json()

  //   
  for (const place in addresses) {
    //  
    const $button = document.createElement('button')

    $button.textContent = place

    //  
    const address = addresses[place]

    //   
    const query = address.replace(
      /([--]+)\s([--]+),\s([0-9--]+)/,
      '$3+$1+$2,+'
    )
    // , , 2++,+

    //     data-
    $button.dataset.address = address
    $button.dataset.query = query

    $addresses.append($button)
  }
})()

//   
$addresses.addEventListener('click', async ({ target }) => {
  if (target.tagName !== 'BUTTON') return

  //    data-
  const { address, query } = target.dataset

  //    
  const response = await fetch(
    `https://nominatim.openstreetmap.org/search?q=${query}&format=json&limit=1`
  )
  // format -  , limit -    

  //  ,   
  const { display_name, lat, lon } = (await response.json())[0]

  //   
  const name = display_name.match(/[--\s(«\-»)]+/)[0]

  const position = [lat, lon]

  //  
  const tooltip = `${name}<br>${address}`

  //  
  getMap(position, tooltip)
})

      
      





Ouvrez index.html. Lorsque vous appuyez sur le premier bouton, nous obtenons immédiatement la position et le nom du théâtre. Lorsque vous appuyez sur le deuxième bouton et les suivants, nous nous déplaçons en douceur entre les cinémas.







Cool. Tout fonctionne comme prévu.



Sur ce, laissez-moi prendre congé. J'espère que vous avez trouvé quelque chose d'intéressant pour vous-même. Merci pour votre attention et bonne journée.



All Articles