PlaceSearchElement est un élément HTML qui affiche les résultats d'une recherche de lieux dans une liste. Il existe deux façons de configurer l'élément gmp-place-search
:
- Utilisez la requête de recherche à proximité pour afficher les résultats de recherche à l'aide de
PlaceNearbySearchRequestElement
- Utilisez la requête de recherche par texte pour afficher les résultats de recherche à l'aide de
PlaceTextSearchRequestElement
.
Demande de recherche à proximité
Sélectionnez un type de lieu dans le menu pour afficher les résultats de recherche à proximité pour ce type de lieu.
L'exemple suivant affiche l'élément Place Search en réponse à une recherche à proximité. Pour plus de simplicité, seuls trois types de lieux sont listés : café, restaurant et borne de recharge pour véhicules électriques. Lorsqu'un résultat est sélectionné, un repère et un
PlaceDetailsCompactElement s'affichent pour le lieu sélectionné. Pour ajouter l'élément Place Search à la carte, ajoutez un élément gmp-place-search
contenant un élément gmp-place-nearby-search-request
à la page HTML, comme indiqué dans l'extrait suivant :
<div class="list-container"> <div id="map-container"></div> <div class="controls"> <select name="types" class="type-select"> <option value="">Select a place type</option> <option value="cafe">Cafe</option> <option value="restaurant">Restaurant</option> <option value="electric_vehicle_charging_station">EV charging station</option> </select> </div> <div class="list-container"> <gmp-place-search orientation="vertical" selectable> <gmp-place-all-content> </gmp-place-all-content> <gmp-place-nearby-search-request ></gmp-place-nearby-search-request> </gmp-place-search> </div> <div id="details-container"> <gmp-place-details-compact orientation="horizontal"> <gmp-place-details-place-request></gmp-place-details-place-request> <gmp-place-all-content></gmp-place-all-content> </gmp-place-details-compact> </div>
Plusieurs appels querySelector
sont utilisés pour sélectionner les éléments de la page avec lesquels interagir :
const mapContainer = document.getElementById("map-container"); const placeSearch = document.querySelector("gmp-place-search"); const placeSearchQuery = document.querySelector("gmp-place-nearby-search-request"); const detailsContainer = document.getElementById("details-container"); const placeDetails = document.querySelector("gmp-place-details-compact"); const placeRequest = document.querySelector("gmp-place-details-place-request"); const typeSelect = document.querySelector(".type-select");
Lorsque l'utilisateur sélectionne un type de lieu dans le menu, l'élément gmp-place-nearby-search-request
est mis à jour et l'élément Place Search affiche les résultats (des repères sont ajoutés dans la fonction d'assistance addMarkers
) :
typeSelect.addEventListener('change', (event) => { event.preventDefault(); searchPlaces(); }); function searchPlaces(){ const bounds = gMap.getBounds(); placeDetailsPopup.map = null; if (typeSelect.value) { placeSearch.style.display = 'block'; placeSearchQuery.maxResultCount = 10; placeSearchQuery.locationRestriction = { center: cent, radius: 1000 }; placeSearchQuery.includedTypes = [typeSelect.value]; placeSearch.addEventListener('gmp-load', addMarkers, { once: true }); } }
Afficher l'exemple de code complet
JavaScript
const mapContainer = document.getElementById("map-container"); const placeSearch = document.querySelector("gmp-place-search"); const placeSearchQuery = document.querySelector("gmp-place-nearby-search-request"); const detailsContainer = document.getElementById("details-container"); const placeDetails = document.querySelector("gmp-place-details-compact"); const placeRequest = document.querySelector("gmp-place-details-place-request"); const typeSelect = document.querySelector(".type-select"); let markers = {}; let gMap; let placeDetailsPopup; let spherical; let AdvancedMarkerElement; let LatLngBounds; let LatLng; async function init() { console.log("init"); ({ spherical } = await google.maps.importLibrary('geometry')); const {Map} = await google.maps.importLibrary("maps"); await google.maps.importLibrary("places"); ({AdvancedMarkerElement} = await google.maps.importLibrary("marker")); ({LatLngBounds, LatLng} = await google.maps.importLibrary("core")); let mapOptions = { center: {lat: -37.813, lng: 144.963}, zoom: 16, mapTypeControl: false, clickableIcons: false, mapId: 'DEMO_MAP_ID' }; gMap = new Map(mapContainer, mapOptions); placeDetailsPopup = new AdvancedMarkerElement({ map: null, content: placeDetails, zIndex: 100 }); findCurrentLocation(); gMap.addListener('click', (e) => { hidePlaceDetailsPopup(); }); typeSelect.addEventListener('change', (event) => { event.preventDefault(); searchPlaces(); }); placeSearch.addEventListener("gmp-select", ({ place }) => { if (markers[place.id]) { markers[place.id].click(); } }); } function searchPlaces(){ const bounds = gMap.getBounds(); const cent = gMap.getCenter(); const ne = bounds.getNorthEast(); const sw = bounds.getSouthWest(); const diameter = spherical.computeDistanceBetween(ne, sw); const cappedRadius = Math.min((diameter / 2 ), 50000); // Radius cannot be more than 50000. placeDetailsPopup.map = null; for(const markerId in markers){ if (Object.prototype.hasOwnProperty.call(markers, markerId)) { markers[markerId].map = null; } } markers = {}; if (typeSelect.value) { mapContainer.style.height = '75vh'; placeSearch.style.display = 'block'; placeSearchQuery.maxResultCount = 10; placeSearchQuery.locationRestriction = { center: cent, radius: cappedRadius }; placeSearchQuery.includedTypes = [typeSelect.value]; placeSearch.addEventListener('gmp-load', addMarkers, { once: true }); console.log("selection!"); console.log(cappedRadius); } } async function addMarkers(){ const bounds = new LatLngBounds(); placeSearch.style.display = 'block'; if(placeSearch.places.length > 0){ placeSearch.places.forEach((place) => { let marker = new AdvancedMarkerElement({ map: gMap, position: place.location }); marker.metadata = {id: place.id}; markers[place.id] = marker; bounds.extend(place.location); marker.addListener('click',(event) => { placeRequest.place = place; placeDetails.style.display = 'block'; placeDetailsPopup.position = place.location; placeDetailsPopup.map = gMap; gMap.fitBounds(place.viewport, {top: 0, left: 400}); placeDetails.addEventListener('gmp-load',() => { gMap.fitBounds(place.viewport, {top: 0, right: 450}); }, { once: true }); }); gMap.setCenter(bounds.getCenter()); gMap.fitBounds(bounds); }); } } async function findCurrentLocation(){ const { LatLng } = await google.maps.importLibrary("core"); if (navigator.geolocation) { navigator.geolocation.getCurrentPosition( (position) => { const pos = new LatLng(position.coords.latitude,position.coords.longitude); gMap.panTo(pos); gMap.setZoom(16); }, () => { console.log('The Geolocation service failed.'); gMap.setZoom(16); }, ); } else { console.log("Your browser doesn't support geolocation"); gMap.setZoom(16); } } function hidePlaceDetailsPopup() { if (placeDetailsPopup.map) { placeDetailsPopup.map = null; placeDetails.style.display = 'none'; } } init();
CSS
html, body { height: 100%; margin: 0; } body { display: flex; flex-direction: column; font-family: Arial, Helvetica, sans-serif; } h1 { font-size: large; text-align: center; } #map-container { flex-grow: 1; max-height:600px; box-sizing: border-box; width: 100%; height: 100vh; } .controls { position: absolute; top: 40px; right: 40px; } .list-container { display: flex; position: absolute; max-height: 500px; top: 80px; right: 40px; overflow-y: none; } .type-select { width: 400px; height: 32px; border: 1px solid #000; border-radius: 10px; flex-grow: 1; padding: 0 10px; } gmp-place-search { width: 400px; margin: 0; border-radius: 10px; display: none; border: none; } gmp-place-details-compact { width: 350px; max-height: 800px; margin-right: 20px; display: none; border: none; } gmp-place-details-compact::after { content: ''; position: absolute; bottom: -18px; left: 50%; transform: translateX(-50%); width: 20px; height: 20px; background-color: white; box-shadow: 2px 2px 5px 0 rgba(0,0,0,0.2); z-index: 1; clip-path: polygon(0% 0%, 100% 0%, 50% 100%); transform-origin: center center; } @media (prefers-color-scheme: dark) { /* Style for Dark mode */ gmp-place-details-compact::after { background-color: #131314; } }
HTML
<!DOCTYPE html> <html> <head> <title>Place Search with Compact Place Details Element</title> <meta charset="utf-8"> <link rel="stylesheet" href="style.css"> <script type="module" src="./index.js"></script> </head> <body> <div id="map-container"></div> <div class="controls"> <select name="types" class="type-select"> <option value="">Select a place type</option> <option value="cafe">Cafe</option> <option value="restaurant">Restaurant</option> <option value="electric_vehicle_charging_station">EV charging station</option> </select> </div> <div class="list-container"> <gmp-place-search orientation="vertical" selectable> <gmp-place-all-content> </gmp-place-all-content> <gmp-place-nearby-search-request ></gmp-place-nearby-search-request> </gmp-place-search> </div> <div id="details-container"> <gmp-place-details-compact orientation="horizontal"> <gmp-place-details-place-request></gmp-place-details-place-request> <gmp-place-all-content></gmp-place-all-content> </gmp-place-details-compact> </div> <script>(g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))}) ({key: "YOUR_API_KEY", v: "weekly"}); </script> </body> </html>
Demande de recherche par texte
Saisissez un terme de recherche dans le champ de saisie, puis cliquez sur le bouton "Rechercher" pour obtenir la liste des lieux correspondant au terme.
Cet exemple affiche l'élément Place Search en réponse à une recherche textuelle de l'utilisateur. Lorsqu'un résultat est sélectionné, un repère et un
PlaceDetailsCompactElement s'affichent pour le lieu sélectionné. Pour ajouter l'élément Place Search à la carte, ajoutez un élément gmp-place-search
contenant un élément gmp-place-search-text-search-request
à la page HTML, comme indiqué dans l'extrait suivant :
<div id="map-container"></div> <div class="controls"> <input type="text" class="query-input" /> <button class="search-button">Search</button> </div> <div class="list-container"> <gmp-place-search orientation="vertical" selectable> <gmp-place-all-content> </gmp-place-all-content> <gmp-place-text-search-request></gmp-place-text-search-request> </gmp-place-search> </div> <div id="details-container"> <gmp-place-details-compact orientation="horizontal"> <gmp-place-details-place-request></gmp-place-details-place-request> <gmp-place-all-content></gmp-place-all-content> </gmp-place-details-compact> </div>
Plusieurs appels querySelector
sont utilisés pour sélectionner les éléments de la page avec lesquels interagir :
const mapContainer = document.getElementById("map-container"); const placeSearch = document.querySelector("gmp-place-search"); const placeSearchQuery = document.querySelector("gmp-place-text-search-request"); const queryInput = document.querySelector(".query-input"); const searchButton = document.querySelector(".search-button"); const detailsContainer = document.getElementById("details-container"); const placeDetails = document.querySelector("gmp-place-details-compact"); const placeRequest = document.querySelector("gmp-place-details-place-request");
Lorsque la fonction de recherche est exécutée après que l'utilisateur a saisi une requête de recherche, l'élément gmp-place-text-search-request
est mis à jour et l'élément Place Search affiche les résultats (des repères sont ajoutés dans la fonction d'assistance addMarkers
) :
searchButton.addEventListener("click", searchPlaces); queryInput.addEventListener("keydown", (event) => { if (event.key == 'Enter') { event.preventDefault(); searchPlaces(); } }); function searchPlaces(){ if (queryInput.value) { placeSearch.style.display = 'block'; placeSearchQuery.textQuery = queryInput.value; placeSearchQuery.locationBias = gMap.getBounds(); placeSearch.addEventListener('gmp-load', addMarkers, { once: true }); } }
Afficher l'exemple de code complet
JavaScript
const mapContainer = document.getElementById("map-container"); const placeSearch = document.querySelector("gmp-place-search"); const placeSearchQuery = document.querySelector("gmp-place-text-search-request"); const queryInput = document.querySelector(".query-input"); const searchButton = document.querySelector(".search-button"); const detailsContainer = document.getElementById("details-container"); const placeDetails = document.querySelector("gmp-place-details-compact"); const placeRequest = document.querySelector("gmp-place-details-place-request"); let markers = {}; let previousSearchQuery = ''; let gMap; let placeDetailsPopup; let AdvancedMarkerElement; let LatLngBounds; let LatLng; async function init() { const {Map} = await google.maps.importLibrary("maps"); await google.maps.importLibrary("places"); ({AdvancedMarkerElement} = await google.maps.importLibrary("marker")); ({LatLngBounds, LatLng} = await google.maps.importLibrary("core")); let mapOptions = { center: {lat: 37.422, lng: -122.085}, zoom: 2, mapTypeControl: false, clickableIcons: false, mapId: 'DEMO_MAP_ID' }; gMap = new Map(mapContainer, mapOptions); placeDetailsPopup = new AdvancedMarkerElement({ map: null, content: placeDetails, zIndex: 100 }); findCurrentLocation(); gMap.addListener('click', (e) => { hidePlaceDetailsPopup(); }); searchButton.addEventListener("click", searchPlaces); queryInput.addEventListener("keydown", (event) => { if (event.key == 'Enter') { event.preventDefault(); searchPlaces(); } }); placeSearch.addEventListener("gmp-select", ({ place }) => { if (markers[place.id]) { markers[place.id].click(); } }); } function searchPlaces(){ if (queryInput.value.trim() === previousSearchQuery) { return; } previousSearchQuery = queryInput.value.trim(); placeDetailsPopup.map = null; for(const markerId in markers){ if (Object.prototype.hasOwnProperty.call(markers, markerId)) { markers[markerId].map = null; } } markers = {}; if (queryInput.value) { // mapContainer.style.height = '75vh'; placeSearch.style.display = 'block'; placeSearchQuery.textQuery = queryInput.value; placeSearchQuery.locationBias = gMap.getBounds(); placeSearch.addEventListener('gmp-load', addMarkers, { once: true }); } } async function addMarkers(){ const bounds = new LatLngBounds(); if(placeSearch.places.length > 0){ placeSearch.places.forEach((place) => { let marker = new AdvancedMarkerElement({ map: gMap, position: place.location }); marker.metadata = {id: place.id}; markers[place.id] = marker; bounds.extend(place.location); marker.addListener('click',(event) => { placeRequest.place = place; placeDetails.style.display = 'block'; placeDetailsPopup.position = place.location; placeDetailsPopup.map = gMap; gMap.fitBounds(place.viewport, {top: 200, right: 450}); }); gMap.setCenter(bounds.getCenter()); gMap.fitBounds(bounds); }); } } async function findCurrentLocation(){ const { LatLng } = await google.maps.importLibrary("core"); if (navigator.geolocation) { navigator.geolocation.getCurrentPosition( (position) => { const pos = new LatLng(position.coords.latitude,position.coords.longitude); gMap.panTo(pos); gMap.setZoom(16); }, () => { console.log('The Geolocation service failed.'); gMap.setZoom(16); }, ); } else { console.log("Your browser doesn't support geolocation"); gMap.setZoom(16); } } function hidePlaceDetailsPopup() { if (placeDetailsPopup.map) { placeDetailsPopup.map = null; placeDetails.style.display = 'none'; } } init();
CSS
html, body { height: 100%; margin: 0; } body { display: flex; flex-direction: column; font-family: Arial, Helvetica, sans-serif; } h1 { font-size: large; text-align: center; } #map-container { flex-grow: 1; max-height:600px; box-sizing: border-box; width: 100%; height: 100vh; } .controls { border-radius: 5px; position: absolute; top: 40px; right: 40px; } .search-button { background-color: #4b4b4b; color: #fff; border: 1px solid #000; border-radius: 10px; width: 80px; height: 40px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.35); } .query-input { border: 1px solid #ccc; border-radius: 10px; width: 315px; height: 40px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.35); } .list-container { display: flex; position: absolute; max-height: 500px; top: 100px; right: 40px; overflow-y: none; } gmp-place-search { width: 400px; margin: 0; border-radius: 10px; display: none; border: none; } gmp-place-details-compact { width: 350px; max-height: 800px; display: none; border: none; transform: translateY(calc(-40%)); } gmp-place-details-compact::after { content: ''; position: absolute; bottom: -18px; left: 50%; transform: translateX(-50%); width: 20px; height: 20px; background-color: white; box-shadow: 2px 2px 5px 0 rgba(0,0,0,0.2); z-index: 1; clip-path: polygon(0% 0%, 100% 0%, 50% 100%); transform-origin: center center; } @media (prefers-color-scheme: dark) { /* Style for Dark mode */ gmp-place-details-compact::after { background-color: #131314; } }
HTML
<!DOCTYPE html> <html> <head> <title>Place Search with a Details Popup</title> <meta charset="utf-8"> <link rel="stylesheet" href="style.css"> <script type="module" src="./index.js"></script> </head> <body> <div id="map-container"></div> <div class="controls"> <input type="text" class="query-input" /> <button class="search-button">Search</button> </div> <div class="list-container"> <gmp-place-search orientation="vertical" selectable> <gmp-place-all-content> </gmp-place-all-content> <gmp-place-text-search-request></gmp-place-text-search-request> </gmp-place-search> </div> <div id="details-container"> <gmp-place-details-compact orientation="horizontal"> <gmp-place-details-place-request></gmp-place-details-place-request> <gmp-place-all-content></gmp-place-all-content> </gmp-place-details-compact> </div> <script>(g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))}) ({key: "YOUR_API_KEY", v: "weekly"}); </script> </body> </html>