PlaceSearchElement
는 장소 검색 결과를 목록으로 렌더링하는 HTML 요소입니다. gmp-place-search 요소는 다음 두 가지 방법으로 구성할 수 있습니다.
-
특정 지역에서 특정 유형의 장소를 검색하려면
주변 검색 요청을 사용하여
PlaceNearbySearchRequestElement를 통해 검색 결과를 렌더링합니다. -
텍스트 쿼리를 기반으로 특정 지역에서 장소를 검색하려면
텍스트로 검색 요청을 사용하여
PlaceTextSearchRequestElement를 통해 검색 결과를 렌더링합니다.
주변 검색 요청
메뉴에서 장소 유형을 선택하여 해당 장소 유형의 주변 검색 결과를 확인합니다.
주변 검색은 주로 장소 유형 및
위치별로 검색하도록 구성되며, 결과를 거리 또는 인기도별로 순위 지정할 수 있습니다.
rankPreference 속성을 사용하여 자세한 내용은
PlaceNearbySearchRequestElement
클래스 참고 문서를 확인하세요.
이 예에서는 사용자가 선택한 장소 유형으로 주변 검색에 대한 응답으로 장소 검색 요소를 렌더링합니다. 또한 선택한 장소의 PlaceDetailsCompactElement 를 표시합니다.
전체 코드 예 보기
지도에 장소 검색 요소를 추가하려면 중첩된
gmp-place-nearby-search-request 요소가 있는
gmp-place-search 요소를 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 요소가 업데이트되고 장소
검색 요소가 다음 스니펫과 같이 결과를 표시합니다.
마커는 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', () => { void addMarkers(); }); searchPlaces(); }
// The searchPlaces function is called when the user changes the type select or when the page loads. 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.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 }] = 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', () => { void addMarkers(); }); searchPlaces(); } // The searchPlaces function is called when the user changes the type select or when the page loads. 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.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) { if (!place.location) continue; const marker = new AdvancedMarkerElement({ map: map.innerMap, position: place.location, 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); } void 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"></script>
<script>
// prettier-ignore
(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: "GOOGLE_MAPS_API_KEY"
});
</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-text-search-request 요소가 있는
gmp-place-search 요소를 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', () => { void addMarkers(); }); searchPlaces(); }
// The searchPlaces function is called when the user changes the query input or when the page loads. 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 }] = 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', () => { void addMarkers(); }); searchPlaces(); } // The searchPlaces function is called when the user changes the query input or when the page loads. 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) { if (!place.location) { continue; } const marker = new AdvancedMarkerElement({ map: map.innerMap, position: place.location, 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); } void 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"></script>
<script>
// prettier-ignore
(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: "GOOGLE_MAPS_API_KEY"
});
</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>