PlaceListElement หรือที่เรียกว่าการค้นหาสถานที่เป็นองค์ประกอบ HTML ที่แสดงผลลัพธ์ของการค้นหาสถานที่เป็นรายการ การกำหนดค่าองค์ประกอบ gmp-place-list
ทำได้ 2 วิธีดังนี้
- ค้นหาคำขอที่อยู่ใกล้เคียงเพื่อกำหนดค่าวิดเจ็ตให้แสดงผลลัพธ์การค้นหาจาก การค้นหาใกล้เคียงของ Places
- ค้นหาตามคำขอแบบข้อความเพื่อกำหนดค่าวิดเจ็ตให้แสดงผลการค้นหาจากการค้นหาแบบข้อความของ Places
ค้นหาคำขอในบริเวณใกล้เคียง
ตัวอย่างต่อไปนี้แสดงผลองค์ประกอบรายการสถานที่เพื่อตอบสนองการค้นหาในพื้นที่ใกล้เคียง เพื่อความสะดวก เราจะแสดงเฉพาะสถานที่ 3 ประเภท ได้แก่ คาเฟ่ ร้านอาหาร และสถานีชาร์จ EV เมื่อเลือกผลการค้นหาแล้ว หน้าต่างข้อมูลจะแสดงรายละเอียดสถานที่สำหรับสถานที่ที่เลือก หากต้องการเพิ่มองค์ประกอบรายการสถานที่ลงในแผนที่ ให้เพิ่มองค์ประกอบ gmp-place-list
ลงในหน้า HTML ดังที่แสดงในข้อมูลโค้ดต่อไปนี้
<gmp-map center="-37.813,144.963" zoom="10" map-id="DEMO_MAP_ID"> <div class="overlay" slot="control-inline-start-block-start"> <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-list selectable style="display: none;"></gmp-place-list> </div> </div> </gmp-map> <gmp-place-details style="display: none;"> <gmp-place-details-place-request></gmp-place-details-place-request> <gmp-place-all-content></gmp-place-all-content> </gmp-place-details>
การเรียกใช้ querySelector
หลายรายการใช้เพื่อเลือกองค์ประกอบหน้าเว็บสำหรับการโต้ตอบ
const map = document.querySelector("gmp-map"); const placeList = document.querySelector("gmp-place-list"); const typeSelect = document.querySelector(".type-select"); const placeDetails = document.querySelector("gmp-place-details"); const placeDetailsRequest = document.querySelector('gmp-place-details-place-request');
เมื่อผู้ใช้คลิกปุ่มค้นหา ระบบจะเรียกใช้
configureFromSearchNearbyRequest
และองค์ประกอบรายการสถานที่จะแสดงผลลัพธ์ (ระบบจะเพิ่มเครื่องหมายในฟังก์ชันตัวช่วย addMarkers
) ข้อมูลโค้ดต่อไปนี้ยังแสดงโค้ดสําหรับการจัดการเหตุการณ์การคลิกในรายการสถานที่โดยใช้เหตุการณ์ gmp-placeselect
ด้วย
placeDetails.addEventListener('gmp-load', (event) => { // Center the info window on the map. map.innerMap.fitBounds(placeDetails.place.viewport, { top: 500, left: 400 }); }); typeSelect.addEventListener('change', (event) => { // First remove all existing markers. for (marker in markers) { markers[marker].map = null; } markers = {}; if (typeSelect.value) { placeList.style.display = 'block'; placeList.configureFromSearchNearbyRequest({ locationRestriction: getContainingCircle(map.innerMap.getBounds()), includedPrimaryTypes: [typeSelect.value], }).then(addMarkers); // Handle user selection in Place Details. placeList.addEventListener('gmp-placeselect', ({ place }) => { markers[place.id].click(); }); } });
ดูตัวอย่างโค้ดที่สมบูรณ์
JavaScript
const map = document.querySelector("gmp-map"); const placeList = document.querySelector("gmp-place-list"); const typeSelect = document.querySelector(".type-select"); const placeDetails = document.querySelector("gmp-place-details"); const placeDetailsRequest = document.querySelector('gmp-place-details-place-request'); let markers = {}; let infoWindow; async function initMap() { await google.maps.importLibrary('places'); const { LatLngBounds } = await google.maps.importLibrary('core'); const { InfoWindow } = await google.maps.importLibrary('maps'); const { spherical } = await google.maps.importLibrary('geometry'); infoWindow = new InfoWindow; let marker; function getContainingCircle(bounds) { const diameter = spherical.computeDistanceBetween(bounds.getNorthEast(), bounds.getSouthWest()); const calculatedRadius = diameter / 2; const cappedRadius = Math.min(calculatedRadius, 50000); // Radius cannot be more than 50000. return { center: bounds.getCenter(), radius: cappedRadius }; } findCurrentLocation(); map.innerMap.setOptions({ mapTypeControl: false, clickableIcons: false, }); placeDetails.addEventListener('gmp-load', (event) => { // Center the info window on the map. map.innerMap.fitBounds(placeDetails.place.viewport, { top: 500, left: 400 }); }); typeSelect.addEventListener('change', (event) => { // First remove all existing markers. for (marker in markers) { markers[marker].map = null; } markers = {}; if (typeSelect.value) { placeList.style.display = 'block'; placeList.configureFromSearchNearbyRequest({ locationRestriction: getContainingCircle(map.innerMap.getBounds()), includedPrimaryTypes: [typeSelect.value], }).then(addMarkers); // Handle user selection in Place Details. placeList.addEventListener('gmp-placeselect', ({ place }) => { markers[place.id].click(); }); } }); } async function addMarkers() { const { AdvancedMarkerElement } = await google.maps.importLibrary('marker'); const { LatLngBounds } = await google.maps.importLibrary('core'); const bounds = new LatLngBounds(); if (placeList.places.length > 0) { placeList.places.forEach((place) => { let marker = new AdvancedMarkerElement({ map: map.innerMap, position: place.location }); markers[place.id] = marker; bounds.extend(place.location); marker.addListener('gmp-click', (event) => { if (infoWindow.isOpen) { infoWindow.close(); } placeDetailsRequest.place = place.id; placeDetails.style.display = 'block'; placeDetails.style.width = '350px'; infoWindow.setOptions({ content: placeDetails, }); infoWindow.open({ anchor: marker, map: map.innerMap }); }); map.innerMap.setCenter(bounds.getCenter()); map.innerMap.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); map.innerMap.panTo(pos); map.innerMap.setZoom(14); }, () => { console.log('The Geolocation service failed.'); map.innerMap.setZoom(14); }); } else { console.log('Your browser doesn\'t support geolocation'); map.innerMap.setZoom(14); } } initMap();
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; } gmp-map { box-sizing: border-box; height: 600px; } .overlay { position: relative; top: 40px; margin: 20px; width: 400px; } .controls { display: flex; gap: 10px; margin-bottom: 10px; height: 32px; } .search-button { background-color: #5491f5; color: #fff; border: 1px solid #ccc; border-radius: 5px; width: 100px; cursor: pointer; } .type-select { border: 1px solid #ccc; border-radius: 5px; flex-grow: 1; padding: 0 10px; } .list-container { height: 400px; overflow: auto; border-radius: 10px; } gmp-place-list { background-color: #fff; font-size: large }
HTML
<!DOCTYPE html> <html> <head> <title>Place List Nearby Search with Google Maps</title> <meta charset="utf-8"> <link rel="stylesheet" type="text/css" href="style.css"> <script type="module" src="./index.js"></script> </head> <body> <gmp-map center="-37.813,144.963" zoom="10" map-id="DEMO_MAP_ID"> <div class="overlay" slot="control-inline-start-block-start"> <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-list selectable style="display: none;"></gmp-place-list> </div> </div> </gmp-map> <gmp-place-details style="display: none;"> <gmp-place-details-place-request></gmp-place-details-place-request> <gmp-place-all-content></gmp-place-all-content> </gmp-place-details> <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: "alpha"});</script> </body> </html>
ลองใช้ตัวอย่าง
ค้นหาตามคำขอข้อความ
ตัวอย่างนี้จะแสดงผลองค์ประกอบรายการสถานที่เพื่อตอบสนองต่อการค้นหาข้อความของผู้ใช้ เมื่อเลือกผลการค้นหาแล้ว หน้าต่างข้อมูลจะแสดงรายละเอียดสถานที่สำหรับสถานที่ที่เลือก หากต้องการเพิ่มองค์ประกอบรายการสถานที่ลงในแผนที่ ให้เพิ่มองค์ประกอบ gmp-place-list
ลงในหน้า HTML ดังที่แสดงในข้อมูลโค้ดต่อไปนี้
<gmp-map center="37.395641,-122.077627" zoom="10" map-id="DEMO_MAP_ID"> <div class="overlay" slot="control-inline-start-block-start"> <div class="text-search-container"> <input type="text" id="textSearchInput" placeholder="Enter text search..."> <button id="textSearchButton">Search</button> </div> <div class="list-container"> <gmp-place-list selectable style="display: none;"></gmp-place-list> </div> </div> <gmp-place-details style="display: none;"> <gmp-place-details-place-request></gmp-place-details-place-request> <gmp-place-all-content></gmp-place-all-content> </gmp-place-details> </gmp-map>
การเรียกใช้ querySelector
หลายรายการใช้เพื่อเลือกองค์ประกอบหน้าเว็บสำหรับการโต้ตอบ
const map = document.querySelector("gmp-map"); const placeList = document.querySelector("gmp-place-list"); const placeDetails = document.querySelector("gmp-place-details"); let marker = document.querySelector('gmp-advanced-marker'); const textSearchInput = document.getElementById('textSearchInput'); const textSearchButton = document.getElementById('textSearchButton'); const placeDetailsRequest = document.querySelector('gmp-place-details-place-request');
เมื่อเรียกใช้ฟังก์ชันการค้นหาหลังจากที่ผู้ใช้ป้อนข้อความค้นหา ระบบจะเรียกใช้
configureFromSearchByTextRequest
และองค์ประกอบรายการสถานที่จะแสดงผลลัพธ์ (มีการเพิ่มเครื่องหมายในฟังก์ชันตัวช่วย addMarkers
) ข้อมูลโค้ดต่อไปนี้แสดงโค้ดของฟังก์ชัน
async function searchByTextRequest() { if (textSearchInput.value !== "") { placeList.style.display = "block"; placeList.configureFromSearchByTextRequest({ locationRestriction: bounds, textQuery: textSearchInput.value, }).then(addMarkers); // Handle user selection in Place Details. placeList.addEventListener("gmp-placeselect", ({ place }) => { markers[place.id].click(); }); } }
ดูตัวอย่างโค้ดที่สมบูรณ์
ตัวอย่างต่อไปนี้ใช้คอมโพเนนต์ UI ของรายการสถานที่เพื่อแสดงสถานที่ตามการค้นหาข้อความโดยใช้
configureFromSearchNearbyRequest
และเพิ่มเครื่องหมายที่คลิกได้ในแผนที่เพื่อแสดงรายละเอียดสถานที่เมื่อเลือก
JavaScript
const map = document.querySelector("gmp-map"); const placeList = document.querySelector("gmp-place-list"); const placeDetails = document.querySelector("gmp-place-details"); let marker = document.querySelector('gmp-advanced-marker'); const textSearchInput = document.getElementById('textSearchInput'); const textSearchButton = document.getElementById('textSearchButton'); const placeDetailsRequest = document.querySelector('gmp-place-details-place-request'); let markers = {}; let infoWindow; let center = { lat: 37.395641, lng: -122.077627 }; // Mountain View, CA. let bounds; async function initMap() { const { Map, InfoWindow } = await google.maps.importLibrary("maps"); const { Place } = await google.maps.importLibrary("places"); // Set bounds for location restriction. bounds = new google.maps.LatLngBounds({ lat: 37.37808200917261, lng: -122.13741583377849 }, { lat: 37.416676154341324, lng: -122.02261728794109 }); infoWindow = new google.maps.InfoWindow; // Center the map map.innerMap.panTo(center); map.innerMap.setZoom(14); map.innerMap.setOptions({ mapTypeControl: false, clickableIcons: false, }); // Fire when the Place Details Element is loaded. placeDetails.addEventListener('gmp-load', (event) => { // Center the info window on the map. map.innerMap.fitBounds(placeDetails.place.viewport, { top: 500, left: 400 }); }); // Handle clicks on the search button. textSearchButton.addEventListener('click', searchByTextRequest); // Handle enter key on text input. textSearchInput.addEventListener('keydown', (event) => { if (event.key === 'Enter') { searchByTextRequest(); } }); } async function searchByTextRequest() { if (textSearchInput.value !== "") { placeList.style.display = "block"; placeList.configureFromSearchByTextRequest({ locationRestriction: bounds, textQuery: textSearchInput.value, }).then(addMarkers); // Handle user selection in Place Details. placeList.addEventListener("gmp-placeselect", ({ place }) => { markers[place.id].click(); }); } } async function addMarkers() { const { AdvancedMarkerElement } = await google.maps.importLibrary("marker"); const { LatLngBounds } = await google.maps.importLibrary("core"); const bounds = new LatLngBounds(); // First remove all existing markers. for (marker in markers) { markers[marker].map = null; } markers = {}; if (placeList.places.length > 0) { placeList.places.forEach((place) => { let marker = new AdvancedMarkerElement({ map: map.innerMap, position: place.location, }); markers[place.id] = marker; bounds.extend(place.location); marker.collisionBehavior = google.maps.CollisionBehavior.REQUIRED_AND_HIDES_OPTIONAL; marker.addListener('gmp-click', (event) => { if (infoWindow.isOpen) { infoWindow.close(); } // Set the Place Details request to the selected place. placeDetailsRequest.place = place.id; placeDetails.style.display = "block"; placeDetails.style.width = "350px"; infoWindow.setOptions({ content: placeDetails }); infoWindow.open({ anchor: marker, map: map.innerMap }); placeDetails.addEventListener('gmp-load', () => { map.innerMap.fitBounds(place.viewport, { top: 400, left: 400 }); }); }); map.innerMap.setCenter(bounds.getCenter()); map.innerMap.fitBounds(bounds); }); } } initMap();
CSS
html, body { height: 100%; margin: 0; } gmp-map { box-sizing: border-box; height: 500px; } gmp-place-list { background-color: #fff; font-size: large } .overlay { position: relative; top: 20px; margin: 20px; width: 400px; } .list-container { height: 400px; overflow: auto; border-radius: 10px; } /* Styles for the text search container and its elements */ .text-search-container { display: flex; /* Arrange input and button side-by-side */ gap: 8px; /* Space between input and button */ padding-bottom: 10px; /* Space below the search bar */ border-bottom: 1px solid #eee; /* Separator line */ } #textSearchInput { flex-grow: 1; /* Allow input to take available space */ padding: 8px 12px; border: 1px solid #ccc; border-radius: 4px; font-size: 1rem; } #textSearchInput:focus { outline: none; border-color: #4a80e8; /* Highlight on focus */ box-shadow: 0 0 0 2px rgba(74, 128, 232, 0.2); } #textSearchButton { padding: 8px 15px; background-color: #4a80e8; /* Example button color */ color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 1rem; transition: background-color 0.2s ease-in-out; } #textSearchButton:hover { background-color: #356ac0; /* Darker shade on hover */ }
HTML
<!DOCTYPE html> <html> <head> <title>Place List 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"></script> </head> <body> <gmp-map center="37.395641,-122.077627" zoom="10" map-id="DEMO_MAP_ID"> <div class="overlay" slot="control-inline-start-block-start"> <div class="text-search-container"> <input type="text" id="textSearchInput" placeholder="Enter text search..."> <button id="textSearchButton">Search</button> </div> <div class="list-container"> <gmp-place-list selectable style="display: none;"></gmp-place-list> </div> </div> <gmp-place-details style="display: none;"> <gmp-place-details-place-request></gmp-place-details-place-request> <gmp-place-all-content></gmp-place-all-content> </gmp-place-details> </gmp-map> <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: "alpha"});</script> </body> </html>