Créer un service de recherche d'établissements à proximité avec Google Maps Platform (JavaScript)

1. Avant de commencer

Découvrez comment utiliser les API Google Maps Platform et Places pour créer une recherche d'établissement local, qui géolocalise l'utilisateur et affiche des lieux intéressants à proximité. L'application intègre la géolocalisation, les informations sur le lieu, Place Photos et plus encore.

Conditions préalables

  • Connaissances de base en HTML, CSS et JavaScript
  • Un projet avec un compte de facturation (suivez les instructions à l'étape suivante si vous n'en avez pas).
  • Pour réaliser l'étape ci-dessous, vous devez activer l'API Maps JavaScript et l'API Places.
  • Clé API pour le projet ci-dessus.

Premiers pas avec Google Maps Platform

Si vous n'avez jamais utilisé Google Maps Platform, suivez le guide Premiers pas avec Google Maps Platform ou regardez la playlist de démarrage avec Google Maps Platform pour effectuer les étapes suivantes :

  1. Créer un compte de facturation
  2. Créer un projet
  3. Activer les SDK et les API Google Maps Platform (répertoriés dans la section précédente)
  4. Générer une clé API

Objectifs de l'atelier

  • Créer une page Web affichant une carte Google
  • Centre la carte sur la position de l'utilisateur
  • Trouver des adresses à proximité et afficher les résultats sous forme de repères cliquables
  • Extraire et afficher plus d'informations sur chaque lieu

Ae1caf211daa484d.png

Prérequis

  • Un navigateur Web, par exemple Google Chrome (recommandé), Firefox, Safari ou Internet Explorer
  • Votre éditeur de texte ou de code favori

Obtenir l'exemple de code

  1. Ouvrez votre interface de ligne de commande (Terminal sous macOS ou Invite de commandes sous Windows), puis téléchargez l'exemple de code à l'aide de la commande suivante:
git clone https://github.com/googlecodelabs/google-maps-nearby-search-js/

Si cela ne fonctionne pas, cliquez sur le bouton suivant pour télécharger l'ensemble du code de cet atelier de programmation, puis décompressez le fichier:

Télécharger le code

  1. Accédez au répertoire que vous venez de cloner ou de télécharger.
cd google-maps-nearby-search-js

Les dossiers stepN contiennent l'état final souhaité de chaque étape de cet atelier de programmation. Ils sont fournis à titre de référence. Effectuez votre codage dans le répertoire work.

2. Créer une carte avec un centre par défaut

Pour créer une carte Google sur votre page Web, trois étapes sont nécessaires:

  1. Créer une page HTML
  2. Ajouter une carte
  3. Collez votre clé API

1. Créer une page HTML

Voici la carte créée lors de cette étape. La carte est centrée sur l'opéra de Sydney, en Australie. Si l'utilisateur refuse l'autorisation d'obtenir sa position, la carte est affichée par défaut pour ce lieu et continue d'afficher des résultats de recherche intéressants.

569b9781658fec74.png

  1. Modifiez les répertoires dans votre dossier work/. Dans la suite de l'atelier de programmation, effectuez les modifications dans la version du dossier work/.
cd work
  1. Dans le répertoire work/, utilisez votre éditeur de texte pour créer un fichier vierge appelé index.html.
  2. Copiez le code suivant dans index.html.

index.html

<!DOCTYPE html>
<html>

<head>
  <title>Sushi Finder</title>
  <meta name="viewport" content="initial-scale=1.0, user-scalable=no">
  <meta charset="utf-8">
  <style>
    /* Always set the map height explicitly to define the size of the div
     * element that contains the map. */
    #map {
      height: 100%;
      background-color: grey;
    }

    /* Optional: Makes the sample page fill the window. */
    html,
    body {
      height: 100%;
      margin: 0;
      padding: 0;
    }

    /* TODO: Step 4A1: Make a generic sidebar. */
  </style>
</head>

<body>
  <!-- TODO: Step 4A2: Add a generic sidebar -->

  <!-- Map appears here -->
  <div id="map"></div>

  <!-- TODO: Step 1B, Add a map -->
</body>

</html>
  1. Ouvrez le fichier index.html dans votre navigateur Web.
open index.html

2. Ajouter une carte

Cette section explique comment charger l'API Maps JavaScript sur votre page Web et écrire votre propre code JavaScript qui utilise l'API pour ajouter une carte à la page Web.

  1. Ajoutez ce code de script à l'emplacement <!-- TODO: Step 1B, Add a map --> après l'élément div map et avant la balise </body> fermante.

step1/index.html

<!-- TODO: Step 1B, Add a map -->
<script>
    /* Note: This example requires that you consent to location sharing when
     * prompted by your browser. If you see the error "Geolocation permission
     * denied.", it means you probably did not give permission for the browser * to locate you. */

    /* TODO: Step 2, Geolocate your user
     * Replace the code from here to the END TODO comment with new code from
     * codelab instructions. */
    let pos;
    let map;
    function initMap() {
        // Set the default location and initialize all variables
        pos = {lat: -33.857, lng: 151.213};
        map = new google.maps.Map(document.getElementById('map'), {
            center: pos,
            zoom: 15
        });
    }
    /* END TODO: Step 2, Geolocate your user */
</script>

<!-- TODO: Step 1C, Get an API key -->
<!-- TODO: Step 3A, Load the Places Library -->
<script async defer src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap">
</script>

3. Collez votre clé API

  1. Dans la ligne après <!-- TODO: Step 1C, Get an API key -->, copiez et remplacez la valeur du paramètre de clé dans l'URL de la source du script par la clé API que vous avez créée lors des prérequis.

step1/index.html

<!-- TODO: Step 1C, Get an API key -->
<!-- TODO: Step 3A, Load the Places Library -->
<script async defer src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap">
</script>
  1. Enregistrez le fichier HTML sur lequel vous travaillez.

Tester le code

Actualisez la vue du fichier que vous avez modifié dans le navigateur. Vous devriez voir une carte apparaître là où le rectangle gris se trouvait auparavant. Si un message d'erreur s'affiche à la place, veillez à remplacer "&YOUR_API_KEY" dans la balise <script> finale par votre propre clé API. Consultez la section ci-dessus pour savoir comment obtenir une clé API si vous n'en avez pas.

Exemple de code complet

Le code complet pour ce projet jusqu'à présent est disponible sur GitHub.

3. Géolocaliser votre utilisateur

Vous souhaitez maintenant afficher la position géographique de l'utilisateur ou de l'appareil sur une carte Google via la fonctionnalité de géolocalisation HTML5 de votre navigateur et l'API Maps JavaScript.

Voici un exemple de carte indiquant votre position géographique si vous naviguez à Mountain View, en Californie:

1dbb3fec117cd895.png

Qu'est-ce que la géolocalisation ?

La géolocalisation correspond à l'identification de la position géographique d'un utilisateur ou d'un appareil informatique par le biais de divers mécanismes de collecte de données. La plupart des services de géolocalisation s'appuient sur des adresses d'acheminement réseau ou des appareils GPS internes pour déterminer cette position. Cette application utilise la propriété Geolocation standard navigator.geolocation du navigateur Web W3C pour déterminer la position de l'utilisateur.

Essayer vous-même

Remplacez le code entre les commentaires TODO: Step 2, Geolocate your user et END TODO: Step 2, Geolocate your user par le code suivant:

step2/index.html

/* TODO: Step 2, Geolocate your user
    * Replace the code from here to the END TODO comment with this code
    * from codelab instructions. */
let pos;
let map;
let bounds;
let infoWindow;
let currentInfoWindow;
let service;
let infoPane;
function initMap() {
    // Initialize variables
    bounds = new google.maps.LatLngBounds();
    infoWindow = new google.maps.InfoWindow;
    currentInfoWindow = infoWindow;
    /* TODO: Step 4A3: Add a generic sidebar */

    // Try HTML5 geolocation
    if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(position => {
        pos = {
        lat: position.coords.latitude,
        lng: position.coords.longitude
        };
        map = new google.maps.Map(document.getElementById('map'), {
        center: pos,
        zoom: 15
        });
        bounds.extend(pos);

        infoWindow.setPosition(pos);
        infoWindow.setContent('Location found.');
        infoWindow.open(map);
        map.setCenter(pos);

        /* TODO: Step 3B2, Call the Places Nearby Search */
    }, () => {
        // Browser supports geolocation, but user has denied permission
        handleLocationError(true, infoWindow);
    });
    } else {
    // Browser doesn't support geolocation
    handleLocationError(false, infoWindow);
    }
}

// Handle a geolocation error
function handleLocationError(browserHasGeolocation, infoWindow) {
    // Set default location to Sydney, Australia
    pos = {lat: -33.856, lng: 151.215};
    map = new google.maps.Map(document.getElementById('map'), {
    center: pos,
    zoom: 15
    });

    // Display an InfoWindow at the map center
    infoWindow.setPosition(pos);
    infoWindow.setContent(browserHasGeolocation ?
    'Geolocation permissions denied. Using default location.' :
    'Error: Your browser doesn\'t support geolocation.');
    infoWindow.open(map);
    currentInfoWindow = infoWindow;

    /* TODO: Step 3B3, Call the Places Nearby Search */
}
/* END TODO: Step 2, Geolocate your user */
/* TODO: Step 3B1, Call the Places Nearby Search */

Tester le code

  1. Enregistrez votre fichier.
  2. Actualisez la page.

Votre navigateur devrait maintenant vous demander l'autorisation de partager votre position avec l'application.

  1. Cliquez une fois sur Bloquer pour voir si elle gère l'erreur de manière fluide et qu'elle reste centrée sur Sydney.
  2. Actualisez de nouveau la page et cliquez sur Autoriser pour vérifier si la géolocalisation fonctionne et déplace la carte vers votre position actuelle.

Exemple de code complet

Le code complet pour ce projet jusqu'à présent est disponible sur GitHub.

4. Rechercher des adresses à proximité

Une requête Nearby Search permet de rechercher des lieux dans une zone définie par mot clé ou par type. Une requête Nearby Search doit toujours inclure un point géographique, qui doit être spécifié en utilisant au choix :

  • Un objet LatLngBounds définissant une zone de recherche rectangulaire
  • Zone circulaire définie en tant que combinaison de la propriété location (spécifiant le centre du cercle en tant qu'objet LatLng) et un rayon (en mètres)

Lancez une recherche à proximité en appelant la méthode nearbySearch() PlacesService, qui renvoie un tableau d'objets PlaceResult.

A. Charger la bibliothèque Places

Tout d'abord, pour accéder aux services de la bibliothèque Places, mettez à jour l'URL de la source de votre script afin d'introduire le paramètre libraries et ajoutez places comme valeur.

step3/index.html

<!-- TODO: Step 3A, Load the Places Library -->
<script async defer
    src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places&callback=initMap">

B. Appelez la fonctionnalité Search Nearby Search et gérez la réponse.

Ensuite, créez une requête PlaceSearch. Les champs obligatoires minimum sont les suivants:

Les champs obligatoires minimum sont les suivants:

  • bounds, qui doit être un objet google.maps.LatLngBounds définissant la zone de recherche rectangulaire, ou un location et un radius ; le premier prend un objet google.maps.LatLng et le second un entier simple représentant le rayon du cercle en mètres. Le rayon maximal autorisé est de 50 000 mètres. Notez que lorsque rankBy est défini sur DISTANCE, vous devez spécifier un lieu, mais pas un rayon ni des limites.
  • keyword pouvant être mis en correspondance avec tous les champs disponibles, y compris, mais sans s'y limiter, le nom, le type et l'adresse, ainsi que les avis de clients et d'autres contenus tiers, ou un type, ce qui limite les résultats aux lieux correspondant au type spécifié. Vous ne pouvez spécifier qu'un seul type (si vous indiquez plusieurs types, tous les types suivants seront ignorés). Consultez la liste des types acceptés.

Dans cet atelier de programmation, vous utiliserez la position actuelle de l'utilisateur en tant qu'emplacement de la recherche, et vous pourrez classer les résultats en fonction de la distance.

  1. Ajoutez le code suivant au commentaire TODO: Step 3B1 pour écrire deux fonctions permettant d'appeler la recherche et de gérer la réponse.

Le mot clé sushi est utilisé comme terme de recherche, mais vous pouvez le modifier. Le code permettant de définir la fonction createMarkers est fourni dans la section suivante.

step3/index.html

/* TODO: Step 3B1, Call the Places Nearby Search */
// Perform a Places Nearby Search Request
function getNearbyPlaces(position) {
    let request = {
    location: position,
    rankBy: google.maps.places.RankBy.DISTANCE,
    keyword: 'sushi'
    };

    service = new google.maps.places.PlacesService(map);
    service.nearbySearch(request, nearbyCallback);
}

// Handle the results (up to 20) of the Nearby Search
function nearbyCallback(results, status) {
    if (status == google.maps.places.PlacesServiceStatus.OK) {
    createMarkers(results);
    }
}

/* TODO: Step 3C, Generate markers for search results */
  1. Ajoutez cette ligne à la fin de la fonction initMap au commentaire TODO: Step 3B2.
/* TODO: Step 3B2, Call the Places Nearby Search */
// Call Places Nearby Search on user's location
getNearbyPlaces(pos);
  1. Ajoutez cette ligne à la fin de la fonction handleLocationError au commentaire TODO: Step 3B3.
/* TODO: Step 3B3, Call the Places Nearby Search */
// Call Places Nearby Search on the default location
getNearbyPlaces(pos);

C. Générer des repères pour les résultats de recherche

Un marqueur identifie un point géographique sur une carte. Par défaut, les marqueurs utilisent des images standard. Pour savoir comment personnaliser les images de repère, consultez Repères.

Le constructeur google.maps.Marker utilise un seul littéral d'objet Marker options spécifiant les propriétés initiales du repère.

Les champs suivants sont particulièrement importants et généralement définis lors de la construction d'un marqueur :

  • position (obligatoire) spécifie un LatLng identifiant l'emplacement initial du repère.
  • map (facultatif) spécifie la carte sur laquelle placer le repère. Si vous ne spécifiez pas la carte lors de sa construction, le repère est créé, mais n'est pas associé (ni affiché) à la carte. Vous pouvez ajouter le repère ultérieurement en appelant la méthode setMap() du repère.
  • Ajoutez le code suivant après le commentaire TODO: Step 3C pour définir la position, la carte et le titre d'un repère par lieu renvoyé dans la réponse. Utilisez également la méthode extend de la variable bounds pour vous assurer que le centre et tous les repères sont visibles sur la carte.

step3/index.html

/* TODO: Step 3C, Generate markers for search results */
// Set markers at the location of each place result
function createMarkers(places) {
    places.forEach(place => {
    let marker = new google.maps.Marker({
        position: place.geometry.location,
        map: map,
        title: place.name
    });

    /* TODO: Step 4B: Add click listeners to the markers */

    // Adjust the map bounds to include the location of this marker
    bounds.extend(place.geometry.location);
    });
    /* Once all the markers have been placed, adjust the bounds of the map to
    * show all the markers within the visible area. */
    map.fitBounds(bounds);
}

/* TODO: Step 4C: Show place details in an info window */

Tester le code

  1. Enregistrez et actualisez la page, puis cliquez sur Autoriser pour accorder des autorisations de géolocalisation.

Vous devez voir jusqu'à 20 repères rouges autour du centre de la carte.

  1. Actualisez la page et bloquez les autorisations de géolocalisation pour le moment.

Obtenez-vous toujours des résultats au centre par défaut de votre carte (dans l'exemple, la valeur par défaut se trouve à Sydney, en Australie) ?

Exemple de code complet

Le code complet pour ce projet jusqu'à présent est disponible sur GitHub.

5. Afficher Place Details sur demande

Une fois que vous avez un identifiant de lieu (affiché dans les champs de votre recherche Nearby), vous pouvez demander des détails supplémentaires, tels que son adresse complète, son numéro de téléphone, ainsi que les notes et les avis des utilisateurs. Dans cet atelier de programmation, vous allez créer une barre latérale pour afficher des détails Place Details détaillés et rendre les repères interactifs pour que l'utilisateur puisse sélectionner des lieux pour voir les détails.

A. Créer une barre latérale générique

Vous avez besoin d'un lieu pour afficher les détails du lieu. Voici un code simple pour une barre latérale qui vous permet de faire glisser le curseur et d'afficher les détails du lieu lorsque l'utilisateur clique sur un repère.

  1. Ajoutez le code suivant à la balise style après le commentaire TODO: Step 4A1:

step4/index.html

/* TODO: Step 4A1: Make a generic sidebar */
/* Styling for an info pane that slides out from the left. 
    * Hidden by default. */
#panel {
    height: 100%;
    width: null;
    background-color: white;
    position: fixed;
    z-index: 1;
    overflow-x: hidden;
    transition: all .2s ease-out;
}

.open {
    width: 250px;
}

/* Styling for place details */
.hero {
    width: 100%;
    height: auto;
    max-height: 166px;
    display: block;
}

.place,
p {
    font-family: 'open sans', arial, sans-serif;
    padding-left: 18px;
    padding-right: 18px;
}

.details {
    color: darkslategrey;
}

a {
    text-decoration: none;
    color: cadetblue;
}
  1. Dans la section body juste avant l'élément div map, ajoutez un élément DIV pour le panneau des détails.
<!-- TODO: Step 4A2: Add a generic sidebar -->
<!-- The slide-out panel for showing place details -->
<div id="panel"></div>
  1. Dans la fonction initMap() après le commentaire TODO: Step 4A3, initialisez la variable infoPane comme suit:
/* TODO: Step 4A3: Add a generic sidebar */
infoPane = document.getElementById('panel');

B. Ajouter des écouteurs de clics aux repères

  1. Dans la fonction createMarkers, ajoutez un écouteur de clics à chaque repère lors de sa création.

L'écouteur de clics extrait les détails du lieu associé à ce repère, puis appelle la fonction pour afficher les détails.

  1. Collez le code suivant dans la fonction createMarkers du commentaire TODO: Step 4B.

La méthode showDetails est implémentée dans la section suivante.

step4/index.html

/* TODO: Step 4B: Add click listeners to the markers */
// Add click listener to each marker
google.maps.event.addListener(marker, 'click', () => {
    let request = {
    placeId: place.place_id,
    fields: ['name', 'formatted_address', 'geometry', 'rating',
        'website', 'photos']
    };

    /* Only fetch the details of a place when the user clicks on a marker.
    * If we fetch the details for all place results as soon as we get
    * the search response, we will hit API rate limits. */
    service.getDetails(request, (placeResult, status) => {
    showDetails(placeResult, marker, status)
    });
});

Dans la requête addListener, la propriété placeId spécifie un lieu unique pour la requête de détails, et la propriété fields est un tableau de noms de champs correspondant aux informations que vous souhaitez obtenir sur le lieu. Pour obtenir la liste complète des champs que vous pouvez demander, consultez l'interface PlaceResult.

C. Afficher les détails du lieu dans une fenêtre d'informations

Une fenêtre d'informations affiche du contenu (généralement du texte ou des images) dans une boîte de dialogue au-dessus d'un emplacement donné sur la carte. La fenêtre d'info est composée d'une zone de contenu et d'un pied effilé. L'extrémité du pied est reliée à un point géographique spécifié sur la carte. En règle générale, les fenêtres d'informations sont associées à des repères, mais vous pouvez également les associer à une latitude/longitude spécifique.

  1. Ajoutez le code suivant au commentaire TODO: Step 4C pour créer un InfoWindow qui affiche le nom et la note de l'établissement, et associe cette fenêtre au repère.

Vous allez définir showPanel dans la section suivante pour afficher les détails dans une barre latérale.

step4/index.html

/* TODO: Step 4C: Show place details in an info window */
// Builds an InfoWindow to display details above the marker
function showDetails(placeResult, marker, status) {
    if (status == google.maps.places.PlacesServiceStatus.OK) {
    let placeInfowindow = new google.maps.InfoWindow();
    placeInfowindow.setContent('<div><strong>' + placeResult.name +
        '</strong><br>' + 'Rating: ' + placeResult.rating + '</div>');
    placeInfowindow.open(marker.map, marker);
    currentInfoWindow.close();
    currentInfoWindow = placeInfowindow;
    showPanel(placeResult);
    } else {
    console.log('showDetails failed: ' + status);
    }
}

/* TODO: Step 4D: Load place details in a sidebar */

D. Charger les détails sur le lieu dans une barre latérale

Utilisez les mêmes informations renvoyées dans l'objet PlaceResult pour insérer un autre élément DIV. Dans cet exemple, utilisez infoPaneun nom de variable arbitraire pour l'élément div associé à l'ID "."panelChaque fois que l'utilisateur clique sur un nouveau repère, ce code ferme la barre latérale si elle est déjà ouverte. Il efface les anciennes informations.

  1. Ajoutez le code suivant après le commentaire TODO: Step 4D.

step4/index.html

/* TODO: Step 4D: Load place details in a sidebar */
// Displays place details in a sidebar
function showPanel(placeResult) {
    // If infoPane is already open, close it
    if (infoPane.classList.contains("open")) {
    infoPane.classList.remove("open");
    }

    // Clear the previous details
    while (infoPane.lastChild) {
    infoPane.removeChild(infoPane.lastChild);
    }

    /* TODO: Step 4E: Display a Place Photo with the Place Details */

    // Add place details with text formatting
    let name = document.createElement('h1');
    name.classList.add('place');
    name.textContent = placeResult.name;
    infoPane.appendChild(name);
    if (placeResult.rating != null) {
    let rating = document.createElement('p');
    rating.classList.add('details');
    rating.textContent = `Rating: ${placeResult.rating} \u272e`;
    infoPane.appendChild(rating);
    }
    let address = document.createElement('p');
    address.classList.add('details');
    address.textContent = placeResult.formatted_address;
    infoPane.appendChild(address);
    if (placeResult.website) {
    let websitePara = document.createElement('p');
    let websiteLink = document.createElement('a');
    let websiteUrl = document.createTextNode(placeResult.website);
    websiteLink.appendChild(websiteUrl);
    websiteLink.title = placeResult.website;
    websiteLink.href = placeResult.website;
    websitePara.appendChild(websiteLink);
    infoPane.appendChild(websitePara);
    }

    // Open the infoPane
    infoPane.classList.add("open");
}

E. Afficher une photo de lieu avec les détails sur ce lieu

Le résultat getDetails renvoie un tableau de 10 photos maximum associées à placeId. Dans cet exemple, la première photo s'affiche au-dessus du nom du lieu dans la barre latérale.

  1. Placez-le avant la création de l'élément name si vous souhaitez que la photo s'affiche en haut de la barre latérale.

step4/index.html

/* TODO: Step 4E: Display a Place Photo with the Place Details */
// Add the primary photo, if there is one
if (placeResult.photos != null) {
    let firstPhoto = placeResult.photos[0];
    let photo = document.createElement('img');
    photo.classList.add('hero');
    photo.src = firstPhoto.getUrl();
    infoPane.appendChild(photo);
}

Tester le code

  1. Enregistrez et actualisez la page dans votre navigateur, puis autorisez les autorisations de géolocalisation.
  2. Cliquez sur un repère pour afficher la fenêtre d'informations qui s'affiche à partir du repère et afficher quelques détails dans la barre latérale de gauche.
  3. Vérifiez si la recherche fonctionne également si vous rechargez et refusez les autorisations de géolocalisation. Modifiez votre mot clé de recherche pour une autre requête et explorez le résultat obtenu.

Ae1caf211daa484d.png

Exemple de code complet

Le code complet pour ce projet jusqu'à présent est disponible sur GitHub.

6. Félicitations

Félicitations ! Vous avez utilisé de nombreuses fonctionnalités de l'API Maps JavaScript, y compris la bibliothèque Places.

Points abordés

Learn more

Pour en savoir plus sur les cartes, explorez la documentation de l'API Maps JavaScript et la documentation Places Library, qui contiennent des guides, des tutoriels, la documentation de référence de l'API, des exemples de code et des canaux d'assistance. Parmi les fonctionnalités populaires, citons Importer des données dans Maps, Commencer à styliser votre carte et ajouter le service Street View.

Quel type d'atelier souhaitez-vous utiliser pour la suite ?

Exemples d'utilisation des informations Places enrichies Autres ateliers de programmation avec l'API JavaScript Maps Platform Autres ateliers de programmation pour Android Autres ateliers de programmation pour iOS Visualiser des données basées sur la localisation sur des cartes Appliquer un style personnalisé aux cartes Utiliser Street View

L'atelier de programmation que vous souhaitez suivre ne figure pas dans la liste ci-dessus ? Demandez-le en décrivant un nouveau problème ici.