Создайте службу поиска предприятий поблизости с помощью платформы Google Maps (JavaScript)

Создайте службу поиска предприятий поблизости с помощью платформы Google Maps (JavaScript)

О практической работе

subjectПоследнее обновление: дек. 3, 2021
account_circleАвторы: Angela Yu

1. Прежде чем вы начнете

Научитесь использовать Google Maps Platform Maps и Places API для создания локального поиска компаний, который определяет геолокацию пользователя и показывает интересные места поблизости. Приложение объединяет геолокацию, сведения о месте, фотографии места и многое другое.

Предпосылки

  • Базовые знания HTML, CSS и JavaScript
  • Проект с платежным аккаунтом (следуйте инструкциям на следующем шаге, если у вас его нет).
  • Для описанного ниже шага включения вам потребуется включить Maps JavaScript API и Places API .
  • Ключ API для вышеуказанного проекта.

Начало работы с платформой Google Карт

Если вы еще не использовали платформу Google Maps, следуйте руководству по началу работы с платформой Google Maps или просмотрите список воспроизведения Начало работы с платформой Google Maps , чтобы выполнить следующие шаги:

  1. Создайте платежный аккаунт.
  2. Создайте проект.
  3. Включите API и SDK платформы Google Карт (перечислены в предыдущем разделе).
  4. Сгенерируйте API-ключ.

Что ты будешь делать

  • Создайте веб-страницу, отображающую карту Google.
  • Центрировать карту по местоположению пользователя
  • Находите близлежащие места и отображайте результаты в виде кликабельных маркеров
  • Получить и показать более подробную информацию о каждом месте

ae1caf211daa484d.png

Что вам понадобится

  • Веб-браузер, например Google Chrome (рекомендуется), Firefox, Safari или Internet Explorer.
  • Ваш любимый текстовый редактор или редактор кода

Получить пример кода

  1. Откройте интерфейс командной строки (терминал в MacOS или командную строку в Windows) и загрузите пример кода с помощью этой команды:
git clone https://github.com/googlecodelabs/google-maps-nearby-search-js/

Если это не сработает, нажмите следующую кнопку, чтобы загрузить весь код для этой лаборатории кода, а затем разархивируйте файл:

Скачать код

  1. Перейдите в каталог, который вы только что клонировали или загрузили.
cd google-maps-nearby-search-js

Папки stepN содержат желаемое конечное состояние каждого шага этой лаборатории кода. Они там для справки. Выполняйте всю свою работу по кодированию в каталоге под названием work .

2. Создайте карту с центром по умолчанию

Чтобы создать карту Google на своей веб-странице, нужно выполнить три шага:

  1. Создать HTML-страницу
  2. Добавить карту
  3. Вставьте свой ключ API

1. Создайте HTML-страницу

Ниже представлена ​​карта, созданная на этом шаге. В центре карты находится Сиднейский оперный театр в Сиднее, Австралия. Если пользователь отказывает в разрешении на получение своего местоположения, карта по умолчанию указывает это местоположение и по-прежнему предоставляет интересные результаты поиска.

569b9781658fec74.png

  1. Измените каталоги на вашу work/ папку. В остальной части кода внесите свои правки в версию в папке work/ .
cd work
  1. В каталоге work/ с помощью текстового редактора создайте пустой файл с именем index.html .
  2. Скопируйте следующий код в index.html .

index.html

<!DOCTYPE html>
<html>

<head>
 
<title>Sushi Finder</title>
 
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
 
<meta charset="utf-8">
 
<style>
   
/* Always set the map height explicitly to define the size of the div
     * element that contains the map. */

   
#map {
     
height: 100%;
     
background-color: grey;
   
}

   
/* Optional: Makes the sample page fill the window. */
    html
,
    body
{
     
height: 100%;
     
margin: 0;
     
padding: 0;
   
}

   
/* TODO: Step 4A1: Make a generic sidebar. */
 
</style>
</head>

<body>
 
<!-- TODO: Step 4A2: Add a generic sidebar -->

 
<!-- Map appears here -->
 
<div id="map"></div>

 
<!-- TODO: Step 1B, Add a map -->
</body>

</html>
  1. Откройте файл index.html в веб-браузере.
open index.html

2. Добавьте карту

В этом разделе показано, как загрузить API JavaScript Карт на свою веб-страницу и написать собственный код JavaScript, использующий API для добавления карты на веб-страницу.

  1. Добавьте этот код скрипта туда, где вы видите <!-- TODO: Step 1B, Add a map --> после элемента div map и перед закрывающим </body> .

шаг1/index.html

<!-- TODO: Step 1B, Add a map -->
<script>
   
/* Note: This example requires that you consent to location sharing when
     * prompted by your browser. If you see the error "Geolocation permission
     * denied.", it means you probably did not give permission for the browser * to locate you. */


   
/* TODO: Step 2, Geolocate your user
     * Replace the code from here to the END TODO comment with new code from
     * codelab instructions. */

    let pos
;
    let map
;
   
function initMap() {
       
// Set the default location and initialize all variables
        pos
= {lat: -33.857, lng: 151.213};
        map
= new google.maps.Map(document.getElementById('map'), {
            center
: pos,
            zoom
: 15
       
});
   
}
   
/* END TODO: Step 2, Geolocate your user */
</script>

<!-- TODO: Step 1C, Get an API key -->
<!-- TODO: Step 3A, Load the Places Library -->
<script async defer src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap">
</script>

3. Вставьте свой ключ API

  1. В строке после <!-- TODO: Step 1C, Get an API key --> скопируйте и замените значение параметра ключа в исходном URL-адресе скрипта на ключ API, созданный во время предварительных требований.

шаг1/index.html

<!-- TODO: Step 1C, Get an API key -->
<!-- TODO: Step 3A, Load the Places Library -->
<script async defer src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap">
</script>
  1. Сохраните файл HTML, над которым вы работали.

Проверь это

Перезагрузите в браузере представление файла, который вы редактировали. Вы должны увидеть, что карта появилась там, где раньше был серый прямоугольник. Если вместо этого вы видите сообщение об ошибке, убедитесь, что вы заменили « YOUR_API_KEY » в последнем <script> своим собственным ключом API. См. выше, как получить ключ API, если у вас его еще нет.

Полный пример кода

Полный код этого проекта до этого момента доступен на Github .

3. Геолокация вашего пользователя

Затем вы хотите отобразить географическое местоположение пользователя или устройства на карте Google, используя функцию геолокации HTML5 вашего браузера вместе с Maps JavaScript API.

Вот пример карты, которая отображает ваше географическое положение, если вы просматривали из Маунтин-Вью, Калифорния:

1dbb3fec117cd895.png

Что такое геолокация?

Геолокация относится к идентификации географического местоположения пользователя или вычислительного устройства с помощью различных механизмов сбора данных. Как правило, большинство служб геолокации используют сетевые адреса маршрутизации или внутренние устройства GPS для определения этого местоположения. Это приложение использует стандартное свойство геолокации W3C веб-браузера navigator.geolocation для определения местоположения пользователя.

Попробуй сам

Замените код между комментариями TODO: Step 2, Geolocate your user и END TODO: Step 2, Geolocate your user следующим кодом:

шаг2/index.html

/* TODO: Step 2, Geolocate your user
    * Replace the code from here to the END TODO comment with this code
    * from codelab instructions. */

let pos
;
let map
;
let bounds
;
let infoWindow
;
let currentInfoWindow
;
let service
;
let infoPane
;
function initMap() {
   
// Initialize variables
    bounds
= new google.maps.LatLngBounds();
    infoWindow
= new google.maps.InfoWindow;
    currentInfoWindow
= infoWindow;
   
/* TODO: Step 4A3: Add a generic sidebar */

   
// Try HTML5 geolocation
   
if (navigator.geolocation) {
    navigator
.geolocation.getCurrentPosition(position => {
        pos
= {
        lat
: position.coords.latitude,
        lng
: position.coords.longitude
       
};
        map
= new google.maps.Map(document.getElementById('map'), {
        center
: pos,
        zoom
: 15
       
});
        bounds
.extend(pos);

        infoWindow
.setPosition(pos);
        infoWindow
.setContent('Location found.');
        infoWindow
.open(map);
        map
.setCenter(pos);

       
/* TODO: Step 3B2, Call the Places Nearby Search */
   
}, () => {
       
// Browser supports geolocation, but user has denied permission
        handleLocationError
(true, infoWindow);
   
});
   
} else {
   
// Browser doesn't support geolocation
    handleLocationError
(false, infoWindow);
   
}
}

// Handle a geolocation error
function handleLocationError(browserHasGeolocation, infoWindow) {
   
// Set default location to Sydney, Australia
    pos
= {lat: -33.856, lng: 151.215};
    map
= new google.maps.Map(document.getElementById('map'), {
    center
: pos,
    zoom
: 15
   
});

   
// Display an InfoWindow at the map center
    infoWindow
.setPosition(pos);
    infoWindow
.setContent(browserHasGeolocation ?
   
'Geolocation permissions denied. Using default location.' :
   
'Error: Your browser doesn\'t support geolocation.');
    infoWindow
.open(map);
    currentInfoWindow
= infoWindow;

   
/* TODO: Step 3B3, Call the Places Nearby Search */
}
/* END TODO: Step 2, Geolocate your user */
/* TODO: Step 3B1, Call the Places Nearby Search */

Проверь это

  1. Сохраните файл.
  2. Перезагрузите свою страницу.

Теперь ваш браузер должен запросить у вас разрешение поделиться своим местоположением с приложением.

  1. Нажмите « Блокировать » один раз, чтобы проверить, корректно ли он обрабатывает ошибку и остается ли он в центре Сиднея.
  2. Перезагрузите снова и нажмите « Разрешить» , чтобы увидеть, работает ли геолокация и перемещает карту в ваше текущее местоположение.

Полный пример кода

Полный код этого проекта до этого момента доступен на Github .

4. Поиск ближайших мест

Поиск поблизости позволяет искать места в указанной области по ключевому слову или типу. Поиск поблизости всегда должен включать местоположение, которое можно указать одним из двух способов:

  • Объект LatLngBounds , определяющий прямоугольную область поиска.
  • Круглая область, определяемая как комбинация свойства location — указание центра круга как объекта LatLng — и радиуса, измеряемого в метрах.

Инициируйте поиск поблизости, вызвав метод PlacesService nearbySearch() службы PlacesService, который вернет массив объектов PlaceResult .

А. Загрузите библиотеку мест

Во-первых, чтобы получить доступ к службам библиотеки мест, обновите исходный URL-адрес сценария, чтобы ввести параметр libraries и добавить places в качестве значения.

шаг3/index.html

<!-- TODO: Step 3A, Load the Places Library -->
<script async defer
   
src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places&callback=initMap">

B. Вызовите запрос на поиск мест поблизости и обработайте ответ

Далее сформируйте запрос PlaceSearch. Минимум обязательных полей:

Минимум обязательных полей:

  • bounds , который должен быть объектом google.maps.LatLngBounds , определяющим прямоугольную область поиска, или location и radius ; первый принимает объект google.maps.LatLng , а второй принимает простое целое число, представляющее радиус круга в метрах. Максимально допустимый радиус составляет 50 000 метров. Обратите внимание, что когда rankBy установлено значение DISTANCE , вы должны указать местоположение, но не можете указать радиус или границы.
  • keyword , которое будет сопоставляться со всеми доступными полями, включая, помимо прочего, имя, тип и адрес, а также отзывы клиентов и другой сторонний контент, или type , который ограничивает результаты местами, соответствующими указанному типу. Можно указать только один тип (если указано более одного типа, то все типы, следующие за первой записью, игнорируются). См. список поддерживаемых типов .

Для этой лаборатории кода вы будете использовать текущее положение пользователя в качестве местоположения для поиска и ранжировать результаты по расстоянию.

  1. Добавьте следующее в комментарий TODO: Step 3B1 , чтобы написать две функции для вызова поиска и обработки ответа.

В качестве поискового запроса используется ключевое слово sushi , но его можно изменить. Код для определения функции createMarkers приведен в следующем разделе.

шаг3/index.html

/* TODO: Step 3B1, Call the Places Nearby Search */
// Perform a Places Nearby Search Request
function getNearbyPlaces(position) {
    let request
= {
    location
: position,
    rankBy
: google.maps.places.RankBy.DISTANCE,
    keyword
: 'sushi'
   
};

    service
= new google.maps.places.PlacesService(map);
    service
.nearbySearch(request, nearbyCallback);
}

// Handle the results (up to 20) of the Nearby Search
function nearbyCallback(results, status) {
   
if (status == google.maps.places.PlacesServiceStatus.OK) {
    createMarkers
(results);
   
}
}

/* TODO: Step 3C, Generate markers for search results */
  1. Добавьте эту строку в конец функции initMap в комментарии TODO: Step 3B2 .
/* TODO: Step 3B2, Call the Places Nearby Search */
// Call Places Nearby Search on user's location
getNearbyPlaces
(pos);
  1. Добавьте эту строку в конец функции handleLocationError в комментарии TODO: Step 3B3 .
/* TODO: Step 3B3, Call the Places Nearby Search */
// Call Places Nearby Search on the default location
getNearbyPlaces
(pos);

C. Создание маркеров для результатов поиска

Маркер определяет местоположение на карте. По умолчанию маркер использует стандартное изображение. Сведения о настройке изображений маркеров см. в разделе Маркеры .

Конструктор google.maps.Marker принимает один литерал объекта Marker options , определяя начальные свойства маркера.

Следующие поля особенно важны и обычно задаются при построении маркера:

  • position (обязательно) указывает LatLng , идентифицирующий начальное местоположение маркера.
  • map (необязательно) указывает карту, на которую нужно поместить маркер. Если вы не укажете карту при построении маркера, маркер будет создан, но не прикреплен к карте (и не отображен на ней). Вы можете добавить маркер позже, вызвав метод маркера setMap() .
  • Добавьте следующий код после комментария TODO: Step 3C , чтобы установить положение, карту и название для одного маркера для каждого места, возвращаемого в ответе. Вы также используете метод extend переменной bounds , чтобы убедиться, что центр и все маркеры видны на карте.

шаг3/index.html

/* TODO: Step 3C, Generate markers for search results */
// Set markers at the location of each place result
function createMarkers(places) {
    places
.forEach(place => {
    let marker
= new google.maps.Marker({
        position
: place.geometry.location,
        map
: map,
        title
: place.name
   
});

   
/* TODO: Step 4B: Add click listeners to the markers */

   
// Adjust the map bounds to include the location of this marker
    bounds
.extend(place.geometry.location);
   
});
   
/* Once all the markers have been placed, adjust the bounds of the map to
    * show all the markers within the visible area. */

    map
.fitBounds(bounds);
}

/* TODO: Step 4C: Show place details in an info window */

Проверь это

  1. Сохраните и перезагрузите страницу, а затем нажмите « Разрешить », чтобы предоставить разрешения на геолокацию.

Вы должны увидеть до 20 красных маркеров вокруг центра карты.

  1. Перезагрузите страницу еще раз и на этот раз заблокируйте разрешения на геолокацию.

Вы по-прежнему получаете результаты в центре карты по умолчанию (в примере по умолчанию находится в Сиднее, Австралия)?

Полный пример кода

Полный код этого проекта до этого момента доступен на Github .

5. Показать информацию о месте по запросу

Получив идентификатор места (введенный в качестве одного из полей в результатах поиска поблизости), вы можете запросить дополнительные сведения о месте, например его полный адрес, номер телефона, рейтинги и отзывы пользователей. В этой кодовой лаборатории вы создадите боковую панель для отображения подробных сведений о месте и сделаете маркеры интерактивными, чтобы пользователь мог выбирать места для просмотра сведений.

A. Сделайте общую боковую панель

Вам нужно место для отображения сведений о месте, поэтому вот простой код для боковой панели, которую вы можете использовать для выдвижения и отображения сведений о месте, когда пользователь нажимает на маркер.

  1. Добавьте следующий код в тег style после комментария TODO: Step 4A1 :

шаг4/index.html

/* TODO: Step 4A1: Make a generic sidebar */
/* Styling for an info pane that slides out from the left.
    * Hidden by default. */

#panel {
    height
: 100%;
    width
: null;
    background
-color: white;
    position
: fixed;
    z
-index: 1;
    overflow
-x: hidden;
    transition
: all .2s ease-out;
}

.open {
    width
: 250px;
}

/* Styling for place details */
.hero {
    width
: 100%;
    height
: auto;
    max
-height: 166px;
    display
: block;
}

.place,
p
{
    font
-family: 'open sans', arial, sans-serif;
    padding
-left: 18px;
    padding
-right: 18px;
}

.details {
    color
: darkslategrey;
}

a
{
    text
-decoration: none;
    color
: cadetblue;
}
  1. В разделе body непосредственно перед div map добавьте div для панели сведений.
<!-- TODO: Step 4A2: Add a generic sidebar -->
<!-- The slide-out panel for showing place details -->
<div id="panel"></div>
  1. В функции initMap() после комментария TODO: Step 4A3 инициализируйте переменную infoPane следующим образом:
/* TODO: Step 4A3: Add a generic sidebar */
infoPane
= document.getElementById('panel');

B. Добавьте прослушиватели кликов к маркерам

  1. В функции createMarkers добавьте прослушиватель кликов к каждому маркеру по мере их создания.

Слушатель кликов извлекает сведения о месте, связанном с этим маркером, и вызывает функцию для отображения сведений.

  1. Вставьте следующий код в функцию createMarkers в комментарии к коду TODO: Step 4B .

Метод showDetails реализуется в следующем разделе.

шаг4/index.html

/* TODO: Step 4B: Add click listeners to the markers */
// Add click listener to each marker
google
.maps.event.addListener(marker, 'click', () => {
    let request
= {
    placeId
: place.place_id,
    fields
: ['name', 'formatted_address', 'geometry', 'rating',
       
'website', 'photos']
   
};

   
/* Only fetch the details of a place when the user clicks on a marker.
    * If we fetch the details for all place results as soon as we get
    * the search response, we will hit API rate limits. */

    service
.getDetails(request, (placeResult, status) => {
    showDetails
(placeResult, marker, status)
   
});
});

В запросе addListener свойство placeId указывает одно место для запроса сведений, а свойство fields представляет собой массив имен полей для информации, которую вы хотите вернуть о месте. Полный список полей, которые вы можете запросить, см. в интерфейсе PlaceResult .

C. Показать сведения о месте в информационном окне

Информационное окно отображает содержимое (обычно текст или изображения) в диалоговом окне над заданным местом на карте. Информационное окно имеет область содержимого и сужающийся стержень. Кончик стебля прикрепляется к указанному месту на карте. Обычно информационные окна прикрепляются к маркерам, но вы также можете прикрепить информационное окно к определенной широте/долготе.

  1. Добавьте следующий код в комментарий TODO: Step 4C , чтобы создать InfoWindow , отображающий название и рейтинг компании, и прикрепить это окно к маркеру.

Вы определяете showPanel в следующем разделе для отображения сведений на боковой панели.

шаг4/index.html

/* TODO: Step 4C: Show place details in an info window */
// Builds an InfoWindow to display details above the marker
function showDetails(placeResult, marker, status) {
   
if (status == google.maps.places.PlacesServiceStatus.OK) {
    let placeInfowindow
= new google.maps.InfoWindow();
    placeInfowindow
.setContent('<div><strong>' + placeResult.name +
       
'</strong><br>' + 'Rating: ' + placeResult.rating + '</div>');
    placeInfowindow
.open(marker.map, marker);
    currentInfoWindow
.close();
    currentInfoWindow
= placeInfowindow;
    showPanel
(placeResult);
   
} else {
    console
.log('showDetails failed: ' + status);
   
}
}

/* TODO: Step 4D: Load place details in a sidebar */

D. Загрузить информацию о месте на боковой панели

Используйте те же сведения, которые возвращаются в объекте PlaceResult , для заполнения другого элемента div. В этом примере используйте infoPane , которое представляет собой произвольное имя переменной для div с идентификатором « panel ». Каждый раз, когда пользователь щелкает новый маркер, этот код закрывает боковую панель, если она уже была открыта, стирает старые данные, добавляет новые данные и открывает боковую панель.

  1. Добавьте следующий код после комментария TODO: Step 4D .

шаг4/index.html

/* TODO: Step 4D: Load place details in a sidebar */
// Displays place details in a sidebar
function showPanel(placeResult) {
   
// If infoPane is already open, close it
   
if (infoPane.classList.contains("open")) {
    infoPane
.classList.remove("open");
   
}

   
// Clear the previous details
   
while (infoPane.lastChild) {
    infoPane
.removeChild(infoPane.lastChild);
   
}

   
/* TODO: Step 4E: Display a Place Photo with the Place Details */

   
// Add place details with text formatting
    let name
= document.createElement('h1');
    name
.classList.add('place');
    name
.textContent = placeResult.name;
    infoPane
.appendChild(name);
   
if (placeResult.rating != null) {
    let rating
= document.createElement('p');
    rating
.classList.add('details');
    rating
.textContent = `Rating: ${placeResult.rating} \u272e`;
    infoPane
.appendChild(rating);
   
}
    let address
= document.createElement('p');
    address
.classList.add('details');
    address
.textContent = placeResult.formatted_address;
    infoPane
.appendChild(address);
   
if (placeResult.website) {
    let websitePara
= document.createElement('p');
    let websiteLink
= document.createElement('a');
    let websiteUrl
= document.createTextNode(placeResult.website);
    websiteLink
.appendChild(websiteUrl);
    websiteLink
.title = placeResult.website;
    websiteLink
.href = placeResult.website;
    websitePara
.appendChild(websiteLink);
    infoPane
.appendChild(websitePara);
   
}

   
// Open the infoPane
    infoPane
.classList.add("open");
}

E. Отображение фотографии места с подробной информацией о месте

Результат getDetails возвращает массив до 10 фотографий, связанных с placeId . Здесь вы показываете первую фотографию над названием места на боковой панели.

  1. Поместите этот код перед созданием элемента name , если вы хотите, чтобы фотография отображалась в верхней части боковой панели.

шаг4/index.html

/* TODO: Step 4E: Display a Place Photo with the Place Details */
// Add the primary photo, if there is one
if (placeResult.photos != null) {
    let firstPhoto
= placeResult.photos[0];
    let photo
= document.createElement('img');
    photo
.classList.add('hero');
    photo
.src = firstPhoto.getUrl();
    infoPane
.appendChild(photo);
}

Проверь это

  1. Сохраните и перезагрузите страницу в браузере и разрешите доступ к геолокации.
  2. Нажмите на маркер, чтобы увидеть всплывающее информационное окно с маркером, отображающим несколько деталей, и боковую панель, выдвигающуюся слева, чтобы отобразить больше деталей.
  3. Проверьте, работает ли поиск, если вы перезагрузите и откажете в разрешениях на геолокацию. Отредактируйте ключевое слово поиска для другого запроса и изучите результат, возвращенный для этого поиска.

ae1caf211daa484d.png

Полный пример кода

Полный код этого проекта до этого момента доступен на Github .

6. Поздравления

Поздравляем! Вы использовали многие функции Maps JavaScript API, в том числе библиотеку Places .

Что мы рассмотрели

Учить больше

Чтобы получить еще больше возможностей для работы с картами, изучите документацию Maps JavaScript API и документацию Places Library , обе из которых содержат руководства, учебные пособия, справку по API, дополнительные примеры кода и каналы поддержки. Некоторые популярные функции включают импорт данных в карты , начало оформления карты и добавление службы просмотра улиц .

Какой тип кодовой лаборатории вы больше всего хотели бы, чтобы мы построили в следующий раз?

Нужная вам кодовая лаборатория не указана выше? Запросите его с новым выпуском здесь .