PlaceSearchElement
הוא אלמנט HTML שמציג את תוצאות החיפוש של מקום ברשימה. יש שתי דרכים להגדיר את רכיב gmp-place-search:
- כדי לחפש מקומות מסוג מסוים באזור נתון, משתמשים בבקשה לחיפוש מקומות בקרבת מקום כדי להציג תוצאות חיפוש באמצעות
PlaceNearbySearchRequestElement. - כדי לחפש מקומות באזור מסוים על סמך שאילתת טקסט, משתמשים בבקשה לחיפוש לפי טקסט כדי להציג תוצאות חיפוש באמצעות
PlaceTextSearchRequestElement.
חיפוש בקשה בקרבת מקום
בוחרים סוג מקום מהתפריט כדי לראות תוצאות חיפוש של מקומות מסוג זה שנמצאים בקרבת מקום.
החיפוש בסביבה הקרובה מוגדר בעיקר לחיפוש לפי סוג מקום ומיקום, ואפשר לדרג את התוצאות לפי מרחק או לפי פופולריות באמצעות המאפיין rankPreference. פרטים נוספים זמינים במאמר
PlaceNearbySearchRequestElementמאמרי העזרה בנושא מחלקות.
בדוגמה הזו, רכיב חיפוש המקומות מוצג בתגובה לחיפוש של מקומות בקרבת מקום עם סוג מקום שנבחר על ידי המשתמש. מוצג גם PlaceDetailsCompactElement של המקום שנבחר.
קוד מלא לדוגמה
כדי להוסיף את רכיב חיפוש המקומות למפה, מוסיפים רכיב gmp-place-search עם רכיב gmp-place-nearby-search-request מוטמע לדף ה-HTML.
<gmp-place-search selectable>
<gmp-place-all-content></gmp-place-all-content>
<gmp-place-nearby-search-request
max-result-count="5"></gmp-place-nearby-search-request>
</gmp-place-search>
רכיב select מאפשר למשתמש לבחור סוג מקום מהתפריט. לצורך הפשטות, מפורטים רק שלושה סוגי מקומות: מסעדה, בית קפה ותחנת טעינה לרכב חשמלי.
<div class="controls">
<label for="type-select">
Select a place type:
<select id="type-select" class="type-select">
<option value="restaurant">Restaurant</option>
<option value="cafe" selected>Cafe</option>
<option value="electric_vehicle_charging_station">
EV charging station
</option>
</select>
</label>
</div>
כשהמשתמש בוחר סוג מקום מהתפריט, הרכיב gmp-place-nearby-search-request מתעדכן, והרכיב Place Search מציג את התוצאות, כמו שמוצג בקטעי הקוד הבאים. הסמנים מתווספים בפונקציית העזר addMarkers.
// Add event listeners to the type select and place search elements. typeSelect.addEventListener('change', () => searchPlaces()); placeSearch.addEventListener('gmp-select', (event) => { const { place } = event; markers.get(place.id)?.click(); }); placeSearch.addEventListener('gmp-load', () => { addMarkers(); }); searchPlaces(); }
// The searchPlaces function is called when the user changes the type select or when the page loads. async function searchPlaces() { // Close the info window and clear the markers. infoWindow.close(); for (const marker of markers.values()) { marker.remove(); } markers.clear(); // Set the place search query and add an event listener to the place search element. if (typeSelect.value) { const center = map.center; placeSearchQuery.locationRestriction = { center, radius: 50000, // 50km radius }; placeSearchQuery.locationBias = { center, }; placeSearchQuery.includedTypes = [typeSelect.value]; } }
דוגמה מלאה לקוד
JavaScript
// Query selectors for various elements in the HTML file. const map = document.querySelector('gmp-map'); const placeSearch = document.querySelector('gmp-place-search'); const placeSearchQuery = document.querySelector('gmp-place-nearby-search-request'); const placeDetails = document.querySelector('gmp-place-details-compact'); const placeRequest = document.querySelector('gmp-place-details-place-request'); const typeSelect = document.querySelector('.type-select'); // Global variables for the map, markers, and info window. const markers = new Map(); let infoWindow; // The init function is called when the page loads. async function init() { // Import the necessary libraries from the Google Maps API. const [{ InfoWindow }, { Place }] = await Promise.all([ google.maps.importLibrary('maps'), google.maps.importLibrary('places'), ]); // Create a new info window and set its content to the place details element. placeDetails.remove(); // Hide the place details element because it is not needed until the info window opens infoWindow = new InfoWindow({ content: placeDetails, ariaLabel: 'Place Details', }); // Set the map options. map.innerMap.setOptions({ clickableIcons: false, mapTypeControl: false, streetViewControl: false, }); // Add event listeners to the type select and place search elements. typeSelect.addEventListener('change', () => searchPlaces()); placeSearch.addEventListener('gmp-select', (event) => { const { place } = event; markers.get(place.id)?.click(); }); placeSearch.addEventListener('gmp-load', () => { addMarkers(); }); searchPlaces(); } // The searchPlaces function is called when the user changes the type select or when the page loads. async function searchPlaces() { // Close the info window and clear the markers. infoWindow.close(); for (const marker of markers.values()) { marker.remove(); } markers.clear(); // Set the place search query and add an event listener to the place search element. if (typeSelect.value) { const center = map.center; placeSearchQuery.locationRestriction = { center, radius: 50000, // 50km radius }; placeSearchQuery.locationBias = { center, }; placeSearchQuery.includedTypes = [typeSelect.value]; } } // The addMarkers function is called when the place search element loads. async function addMarkers() { // Import the necessary libraries from the Google Maps API. const [{ AdvancedMarkerElement }, { LatLngBounds }] = await Promise.all([ google.maps.importLibrary('marker'), google.maps.importLibrary('core'), ]); const bounds = new LatLngBounds(); if (placeSearch.places.length === 0) { return; } for (const place of placeSearch.places) { const marker = new AdvancedMarkerElement({ map: map.innerMap, position: place.location, collisionBehavior: google.maps.CollisionBehavior.REQUIRED_AND_HIDES_OPTIONAL, }); markers.set(place.id, marker); bounds.extend(place.location); marker.addListener('click', () => { placeRequest.place = place; infoWindow.open(map.innerMap, marker); }); } map.innerMap.fitBounds(bounds); } init();
CSS
html, body { height: 100%; margin: 0; } body { display: flex; flex-direction: column; font-family: Arial, Helvetica, sans-serif; } .container { display: flex; height: 100vh; width: 100%; } gmp-map { flex-grow: 1; } .ui-panel { width: 400px; margin-left: 20px; margin-top: 10px; overflow-y: auto; font-family: Arial, Helvetica, sans-serif; } .list-container { display: flex; flex-direction: column; } gmp-place-search { width: 100%; margin: 0; border: none; color-scheme: light; }
HTML
<!doctype html>
<html>
<head>
<title>Place Search Nearby with Google Maps</title>
<meta charset="utf-8" />
<link rel="stylesheet" type="text/css" href="style.css" />
<script type="module" src="./index.js" defer></script>
<!-- prettier-ignore -->
<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: "AIzaSyA6myHzS10YXdcazAFalmXvDkrYCp5cLc8", v: "weekly"});
</script>
</head>
<body>
<div class="container">
<!-- map-id is required to use advanced markers. See https://developers.google.com/maps/documentation/javascript/map-ids/mapid-over. -->
<gmp-map center="-37.813,144.963" zoom="16" map-id="DEMO_MAP_ID">
</gmp-map>
<div class="ui-panel">
<div class="controls">
<label for="type-select">
Select a place type:
<select id="type-select" class="type-select">
<option value="restaurant">Restaurant</option>
<option value="cafe" selected>Cafe</option>
<option value="electric_vehicle_charging_station">
EV charging station
</option>
</select>
</label>
</div>
<div class="list-container">
<gmp-place-search selectable>
<gmp-place-all-content></gmp-place-all-content>
<gmp-place-nearby-search-request
max-result-count="5"></gmp-place-nearby-search-request>
</gmp-place-search>
</div>
</div>
</div>
<!--
The gmp-place-details-compact element is styled inline because it is
conditionally rendered and moved into the info window, which is
part of the map's shadow DOM.
-->
<gmp-place-details-compact
orientation="horizontal"
truncation-preferred
style="
width: 400px;
padding: 0;
margin: 0;
border: none;
background-color: transparent;
color-scheme: light;
">
<gmp-place-details-place-request></gmp-place-details-place-request>
<gmp-place-content-config>
<gmp-place-media></gmp-place-media>
<gmp-place-rating></gmp-place-rating>
<gmp-place-price></gmp-place-price>
<gmp-place-accessible-entrance-icon></gmp-place-accessible-entrance-icon>
<gmp-place-open-now-status></gmp-place-open-now-status>
<gmp-place-attribution
light-scheme-color="gray"
dark-scheme-color="white"></gmp-place-attribution>
</gmp-place-content-config>
</gmp-place-details-compact>
</body>
</html>דוגמה לניסיון
חיפוש באמצעות בקשת טקסט
מזינים מונח חיפוש בשדה הקלט ולוחצים על הלחצן חיפוש כדי לקבל רשימה של מקומות שתואמים למונח.
חיפוש הטקסט מוגדר בעיקר לחיפוש באמצעות שאילתת טקסט ומיקום, ואפשר לצמצם את התוצאות לפי רמת מחיר, דירוג והאם המקום פתוח כרגע. אפשר גם לדרג את התוצאות לפי מרחק או לפי פופולריות באמצעות המאפיין rankPreference. פרטים נוספים זמינים במאמר
PlaceTextSearchRequestElementמאמרי העזרה בנושא מחלקות.
בדוגמה הזו, רכיב חיפוש המקומות מוצג בתגובה לקלט טקסט של משתמש. מוצג גם PlaceDetailsCompactElement של המקום שנבחר.
קוד מלא לדוגמה
כדי להוסיף את רכיב חיפוש המקומות למפה, מוסיפים רכיב gmp-place-search עם רכיב gmp-place-search-text-search-request מוטמע לדף ה-HTML.
<gmp-place-search selectable>
<gmp-place-all-content></gmp-place-all-content>
<gmp-place-text-search-request
max-result-count="5"></gmp-place-nearby-search-request>
</gmp-place-search>
הרכיב input מאפשר למשתמש להזין טקסט לחיפוש.
<div class="controls">
<input
type="text"
id="query-input"
class="query-input"
placeholder="Search for a place"
value="cafe" />
<button id="search-button" class="search-button">
Search
</button>
</div>
כשמשתמש לוחץ על הלחצן חיפוש, פונקציית החיפוש מופעלת, רכיב gmp-place-text-search-request מתעדכן ורכיב חיפוש המקומות מציג את התוצאות כמו שמוצג בקטעי הקוד הבאים. הסמנים מתווספים בפונקציית העזר addMarkers.
// Add event listeners to the query input and place search elements. searchButton.addEventListener('click', () => searchPlaces()); queryInput.addEventListener('keydown', (event) => { if (event.key === 'Enter') { searchPlaces(); } }); placeSearch.addEventListener('gmp-select', (event) => { const { place } = event; markers.get(place.id)?.click(); }); placeSearch.addEventListener('gmp-load', () => { addMarkers(); }); searchPlaces(); }
// The searchPlaces function is called when the user changes the query input or when the page loads. async function searchPlaces() { // Close the info window and clear the markers. infoWindow.close(); for (const marker of markers.values()) { marker.remove(); } markers.clear(); // Set the place search query and add an event listener to the place search element. if (queryInput.value) { const center = map.center; if (center) { placeSearchQuery.locationBias = center; } // The textQuery property is required for the search element to load. // Any other configured properties will be ignored if textQuery is not set. placeSearchQuery.textQuery = queryInput.value; } }
דוגמה מלאה לקוד
JavaScript
// Query selectors for various elements in the HTML file. const map = document.querySelector('gmp-map'); const placeSearch = document.querySelector('gmp-place-search'); const placeSearchQuery = document.querySelector('gmp-place-text-search-request'); const placeDetails = document.querySelector('gmp-place-details-compact'); const placeRequest = document.querySelector('gmp-place-details-place-request'); const queryInput = document.querySelector('.query-input'); const searchButton = document.querySelector('.search-button'); // Global variables for the map, markers, and info window. const markers = new Map(); let infoWindow; // The init function is called when the page loads. async function init() { // Import the necessary libraries from the Google Maps API. const [{ InfoWindow }, { Place }] = await Promise.all([ google.maps.importLibrary('maps'), google.maps.importLibrary('places'), ]); // Create a new info window and set its content to the place details element. placeDetails.remove(); // Hide the place details element because it is not needed until the info window opens infoWindow = new InfoWindow({ content: placeDetails, ariaLabel: 'Place Details', }); // Set the map options. map.innerMap.setOptions({ clickableIcons: false, mapTypeControl: false, streetViewControl: false, }); // Add event listeners to the query input and place search elements. searchButton.addEventListener('click', () => searchPlaces()); queryInput.addEventListener('keydown', (event) => { if (event.key === 'Enter') { searchPlaces(); } }); placeSearch.addEventListener('gmp-select', (event) => { const { place } = event; markers.get(place.id)?.click(); }); placeSearch.addEventListener('gmp-load', () => { addMarkers(); }); searchPlaces(); } // The searchPlaces function is called when the user changes the query input or when the page loads. async function searchPlaces() { // Close the info window and clear the markers. infoWindow.close(); for (const marker of markers.values()) { marker.remove(); } markers.clear(); // Set the place search query and add an event listener to the place search element. if (queryInput.value) { const center = map.center; if (center) { placeSearchQuery.locationBias = center; } // The textQuery property is required for the search element to load. // Any other configured properties will be ignored if textQuery is not set. placeSearchQuery.textQuery = queryInput.value; } } // The addMarkers function is called when the place search element loads. async function addMarkers() { // Import the necessary libraries from the Google Maps API. const [{ AdvancedMarkerElement }, { LatLngBounds }] = await Promise.all([ google.maps.importLibrary('marker'), google.maps.importLibrary('core'), ]); const bounds = new LatLngBounds(); if (placeSearch.places.length === 0) { return; } for (const place of placeSearch.places) { const marker = new AdvancedMarkerElement({ map: map.innerMap, position: place.location, collisionBehavior: google.maps.CollisionBehavior.REQUIRED_AND_HIDES_OPTIONAL, }); markers.set(place.id, marker); bounds.extend(place.location); marker.addListener('click', () => { placeRequest.place = place; infoWindow.open(map.innerMap, marker); }); } map.innerMap.fitBounds(bounds); } init();
CSS
html, body { height: 100%; margin: 0; } body { display: flex; flex-direction: column; font-family: Arial, Helvetica, sans-serif; } .container { display: flex; height: 100vh; width: 100%; } gmp-map { flex-grow: 1; } .ui-panel { width: 400px; margin-left: 20px; margin-right: 20px; margin-top: 10px; overflow-y: auto; font-family: Arial, Helvetica, sans-serif; } .list-container { display: flex; flex-direction: column; } gmp-place-search { width: 100%; margin: 0; border: none; color-scheme: light; } .query-input { width: 100%; padding: 8px; margin-bottom: 10px; box-sizing: border-box; } .search-button { width: 100%; padding: 8px; margin-bottom: 10px; box-sizing: border-box; background-color: #1a73e8; color: white; border: none; cursor: pointer; } .search-button:hover, .search-button:focus-visible { background-color: #1765cc; }
HTML
<!DOCTYPE html>
<html>
<head>
<title>Place Text Search with Google Maps</title>
<meta charset="utf-8" />
<link rel="stylesheet" type="text/css" href="style.css" />
<script type="module" src="./index.js" defer></script>
<!-- prettier-ignore -->
<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: "AIzaSyA6myHzS10YXdcazAFalmXvDkrYCp5cLc8", v: "weekly"});
</script>
</head>
<body>
<div class="container">
<div class="ui-panel">
<div class="controls">
<input
type="text"
id="query-input"
class="query-input"
placeholder="Search for a place"
value="cafe" />
<button class="search-button">Search</button>
</div>
<div class="list-container">
<gmp-place-search selectable>
<gmp-place-all-content></gmp-place-all-content>
<gmp-place-text-search-request
max-result-count="5"></gmp-place-text-search-request>
</gmp-place-search>
</div>
</div>
<!-- map-id is required to use advanced markers. See https://developers.google.com/maps/documentation/javascript/map-ids/mapid-over. -->
<gmp-map center="-37.813,144.963" zoom="16" map-id="DEMO_MAP_ID">
</gmp-map>
</div>
<!--
The gmp-place-details-compact element is styled inline because it is
conditionally rendered and moved into the info window, which is
part of the map's shadow DOM.
-->
<gmp-place-details-compact
orientation="horizontal"
truncation-preferred
style="
width: 400px;
padding: 0;
margin: 0;
border: none;
background-color: transparent;
color-scheme: light;
">
<gmp-place-details-place-request></gmp-place-details-place-request>
<gmp-place-content-config>
<gmp-place-media></gmp-place-media>
<gmp-place-rating></gmp-place-rating>
<gmp-place-price></gmp-place-price>
<gmp-place-accessible-entrance-icon></gmp-place-accessible-entrance-icon>
<gmp-place-open-now-status></gmp-place-open-now-status>
<gmp-place-attribution
light-scheme-color="gray"
dark-scheme-color="white"></gmp-place-attribution>
</gmp-place-content-config>
</gmp-place-details-compact>
</body>
</html>