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

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, дополнительные примеры кода и каналы поддержки. Некоторые популярные функции включают импорт данных в карты , начало оформления карты и добавление службы просмотра улиц .

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

Другие примеры использования расширенной информации Places Другие лабораторные работы с использованием API JavaScript платформы Карт Больше лабораторий кода для Android Больше лабораторий кода для iOS Визуализация данных о местоположении на картах Пользовательский стиль карт Использование просмотра улиц

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