|
5 | 5 | */ |
6 | 6 |
|
7 | 7 | // [START maps_place_nearby_search] |
8 | | -let map; |
| 8 | +const mapElement = document.querySelector('gmp-map') as google.maps.MapElement; |
| 9 | +let innerMap; |
| 10 | +const advancedMarkerElement = document.querySelector('gmp-advanced-marker') as google.maps.marker.AdvancedMarkerElement; |
| 11 | +let center; |
| 12 | +let typeSelect; |
| 13 | +let infoWindow; |
9 | 14 |
|
10 | 15 | async function initMap() { |
11 | 16 | const { Map, InfoWindow } = await google.maps.importLibrary('maps') as google.maps.MapsLibrary; |
| 17 | + const { LatLng } = await google.maps.importLibrary("core") as google.maps.CoreLibrary; |
12 | 18 |
|
13 | | - let center = new google.maps.LatLng(52.369358, 4.889258); |
14 | | - |
15 | | - map = new Map(document.getElementById('map') as HTMLElement, { |
16 | | - center: center, |
17 | | - zoom: 11, |
18 | | - mapId: 'DEMO_MAP_ID', |
| 19 | + innerMap = mapElement.innerMap; |
| 20 | + innerMap.setOptions({ |
19 | 21 | mapTypeControl: false, |
20 | 22 | }); |
| 23 | + |
| 24 | + typeSelect = document.querySelector(".type-select"); |
| 25 | + |
| 26 | + typeSelect.addEventListener('change', () => { |
| 27 | + nearbySearch(); |
| 28 | + }); |
| 29 | + |
| 30 | + infoWindow = new InfoWindow(); |
| 31 | + |
| 32 | + // Kick off an initial search. |
21 | 33 | nearbySearch(); |
22 | 34 | } |
23 | 35 |
|
24 | 36 | async function nearbySearch() { |
25 | | - //@ts-ignore |
26 | 37 | const { Place, SearchNearbyRankPreference } = await google.maps.importLibrary('places') as google.maps.PlacesLibrary; |
27 | 38 | const { AdvancedMarkerElement } = await google.maps.importLibrary("marker") as google.maps.MarkerLibrary; |
| 39 | + const { spherical } = await google.maps.importLibrary('geometry') as google.maps.GeometryLibrary; |
28 | 40 | // [START maps_place_nearby_search_request] |
29 | | - |
30 | | - // Restrict within the map viewport. |
31 | | - let center = new google.maps.LatLng(52.369358, 4.889258); |
| 41 | + // Get bounds and radius to constrain search. |
| 42 | + center = mapElement.center; |
| 43 | + let bounds = innerMap.getBounds(); |
| 44 | + const ne = bounds.getNorthEast(); |
| 45 | + const sw = bounds.getSouthWest(); |
| 46 | + const diameter = spherical.computeDistanceBetween(ne, sw); |
| 47 | + const radius = Math.min((diameter / 2), 50000); // Radius cannot be more than 50000. |
32 | 48 |
|
33 | 49 | const request = { |
34 | 50 | // required parameters |
35 | | - fields: ['displayName', 'location', 'businessStatus'], |
| 51 | + fields: ['displayName', 'location', 'formattedAddress', 'googleMapsURI'], |
36 | 52 | locationRestriction: { |
37 | | - center: center, |
38 | | - radius: 500, |
| 53 | + center, |
| 54 | + radius, |
39 | 55 | }, |
40 | 56 | // optional parameters |
41 | | - includedPrimaryTypes: ['restaurant'], |
| 57 | + includedPrimaryTypes: [typeSelect.value], |
42 | 58 | maxResultCount: 5, |
43 | 59 | rankPreference: SearchNearbyRankPreference.POPULARITY, |
44 | | - language: 'en-US', |
45 | | - region: 'us', |
46 | 60 | }; |
47 | 61 |
|
48 | | - //@ts-ignore |
49 | 62 | const { places } = await Place.searchNearby(request); |
50 | 63 | // [END maps_place_nearby_search_request] |
51 | 64 |
|
52 | 65 | if (places.length) { |
53 | | - console.log(places); |
54 | | - |
55 | 66 | const { LatLngBounds } = await google.maps.importLibrary("core") as google.maps.CoreLibrary; |
56 | 67 | const bounds = new LatLngBounds(); |
57 | 68 |
|
| 69 | + // First remove all existing markers. |
| 70 | + for (const marker of mapElement.querySelectorAll('gmp-advanced-marker')) marker.remove(); |
| 71 | + |
58 | 72 | // Loop through and get all the results. |
59 | | - places.forEach((place) => { |
60 | | - const markerView = new AdvancedMarkerElement({ |
61 | | - map, |
| 73 | + places.forEach(place => { |
| 74 | + if (!place.location) return; |
| 75 | + bounds.extend(place.location); |
| 76 | + |
| 77 | + const marker = new AdvancedMarkerElement({ |
| 78 | + map: innerMap, |
62 | 79 | position: place.location, |
63 | 80 | title: place.displayName, |
64 | 81 | }); |
65 | 82 |
|
66 | | - bounds.extend(place.location as google.maps.LatLng); |
67 | | - console.log(place); |
| 83 | + // Build the content of the InfoWindow safely using DOM elements. |
| 84 | + const content = document.createElement('div'); |
| 85 | + const address = document.createElement('div'); |
| 86 | + address.textContent = place.formattedAddress || ''; |
| 87 | + const placeId = document.createElement('div'); |
| 88 | + placeId.textContent = place.id; |
| 89 | + content.append(address, placeId); |
| 90 | + |
| 91 | + if (place.googleMapsURI) { |
| 92 | + const link = document.createElement('a'); |
| 93 | + link.href = place.googleMapsURI; |
| 94 | + link.target = '_blank'; |
| 95 | + link.textContent = 'View Details on Google Maps'; |
| 96 | + content.appendChild(link); |
| 97 | + } |
| 98 | + |
| 99 | + marker.addListener('gmp-click', () => { |
| 100 | + innerMap.panTo(place.location); |
| 101 | + updateInfoWindow(place.displayName, content, marker); |
| 102 | + }); |
68 | 103 | }); |
69 | | - |
70 | | - map.fitBounds(bounds); |
| 104 | + |
| 105 | + innerMap.fitBounds(bounds, 100); |
71 | 106 |
|
72 | 107 | } else { |
73 | | - console.log("No results"); |
| 108 | + console.log('No results'); |
74 | 109 | } |
75 | 110 | } |
76 | 111 |
|
| 112 | +function updateInfoWindow(title, content, anchor) { |
| 113 | + infoWindow.setContent(content); |
| 114 | + infoWindow.setHeaderContent(title); |
| 115 | + infoWindow.open({ |
| 116 | + anchor, |
| 117 | + }); |
| 118 | +} |
| 119 | + |
77 | 120 | initMap(); |
78 | 121 | // [END maps_place_nearby_search] |
0 commit comments