地点搜索元素

请选择平台: Android iOS JavaScript

PlaceSearchElement 是一种 HTML 元素,用于以列表形式呈现地点搜索结果。您可以通过以下两种方式配置 gmp-place-search 元素:

搜索附近地点的请求

从菜单中选择地点类型,即可查看该地点类型附近的搜索结果。

以下示例展示了如何响应附近搜索来呈现地点搜索元素。为简单起见,此处仅列出三种地点类型:咖啡馆、餐厅和电动汽车充电站。选择某个结果后,系统会显示所选地点的标记和 PlaceDetailsCompactElement。如需将地点搜索元素添加到地图,请将包含 gmp-place-nearby-search-request 元素的 gmp-place-search 元素添加到 HTML 页面,如以下代码段所示:

<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>

使用多个 querySelector 调用来选择要进行互动的网页元素:

 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");

当用户从菜单中选择地点类型时,gmp-place-nearby-search-request 元素会更新,并且地点搜索元素会显示结果(标记是在 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 });  } }

查看完整的代码示例

 
   

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>
 

按文字搜索请求

在输入字段中输入搜索字词,然后点击“搜索”按钮,即可获取与该字词匹配的地点列表。

此示例会呈现地点搜索元素,以响应用户文本搜索。选择结果后,系统会显示所选地点的标记和 PlaceDetailsCompactElement。如需将地点搜索元素添加到地图中,请向 HTML 页面添加一个包含 gmp-place-search-text-search-request 元素的 gmp-place-search 元素,如以下代码段所示:

 <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> 

使用多个 querySelector 调用来选择要进行互动的网页元素:

 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");

当用户输入搜索查询后运行搜索功能时,gmp-place-text-search-request 元素会更新,地点搜索元素会显示结果(在 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 });  } }

查看完整的代码示例

 
   

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>