От автора: Функциональность геолокации и трекинга стремительно развивается. От статичных карт мы перешли на интерактивные и динамические технологии. Мы видим, насколько важно отслеживание геолокации в реальном времени стало для приложений во всех областях, от экономики услуг по заказу до интернета вещей.
Наблюдайте за тем, как Uber или Днае едет к вам
Просматривайте и подсвечивайте области повышенного риска для лечения болезни
Мониторинг парка беспилотников
Отслеживайте животных в охраняемых национальных парках
Отслеживание в реальном времени раскинуло свои широкие сети, да?
Обзор урока
Ниже представлен урок из 4 частей по созданию карты в реальном времени для веба и мобильного веба с помощью Google Maps JavaScript API и PubNub. Начнем с базовой настройки приложения, а геолокацию в реальном времени добавим в частях 2-4.
В конце вы получите базовое приложение с отслеживанием локации через JS с маркерами карты, отслеживанием локации устройства и маршрутами полетов. Все это под управлением JavaScript Google Maps API и PubNub.
Файлы урока
В уроке исходим из того, что вы работаете в последней версии браузера на десктопе или мобильном устройстве.
Код примеров, используемых в серии уроков, доступен в коллекции CodePen. Вы можете легко скопировать их в свой проект и обновить своими API ключами и кастомной функциональностью.
У вас должен быть бесплатный профиль на CodePen для копирования, изменения и сохранения демо. Также можно скачать HTML и предоставлять его с помощью другого механизма (Python SimpleHttpServer или облачный файловый сервер с доступом к HTML)! Весь код независим от CodePen.
Часть 1: настройка JavaScript, Google Maps API и PubNub Setup
Настройка окружения и регистрация в сервисах Google Maps и PubNub.
Настройка PubNub
Для начала нужно получить ключи публикации и подписки PubNub. Если у вас нет профиля, можете зарегистрироваться здесь. Ключи доступны в Admin Dashboard.
После получения ключей создайте новое PubNub приложение, представляющее ваше Android приложение (и любую другую систему, которая взаимодействует по тем же каналам). Приложение PubNub подключит ключи, а приложение сможет с их помощью выполнять свои функции.
Настройка Google Maps API
Для интеграции с Google Maps нужно создать ключ Google Maps API. Рекомендуем сделать это, прочитав руководство. Будет создан уникальный ключ API, который можно привязать к любым веб-приложениям.
После создания нескольких проектов управлять учетными данными можно в Google API console.
Обзор PubNub
В этом HTML5 и JS примере приложения PubNub предоставляет возможность взаимодействия в реальном времени. Наше веб-приложение может получать входящие события по мере изменения позиции удаленного объекта (широта и долгота).
Мы используем функциональность ядра PubNub Realtime Messaging. Наше приложение использует канал PubNub для отправки и получения событий изменения позиции. В этом примере одно и то же приложение посылает и получает события положения, поэтому его можно назвать издателем и подписчиком. В вашем приложении система(ы) издателя (отправителя) может отличаться от системы подписчика (получателя).
Обзор Google Maps
Для урока воспользуемся JavaScript Google Maps API и HTML5 Map Widget. HTML5 map widget отображает карту настроенной области. Размер карты, центральную широту и долготу, уровень масштабирования, стиль карты и другие опции можно установить в первичных настройках. Эти значения можно обновлять налету.
Google Maps JavaScript API предоставляет опцию колбек инициализации, которая вызывает функцию, указанную при загрузке карты.
Также будем использовать функции типа Map Markers и Polylines, которые позволяют размещать дружелюбные маркеры и маршруты полетов на карте в заданной локации(ях) (часть 2,3 и 4). Все точки задаются пользователем и могут обновляться в реальном времени при получении этих обновлений.
Работа с кодом
Рассмотрим код. Для работы с кодом можно скопировать его в свой проект с помощью CodePen или загрузить HTML в файл и запустить его на HTTP сервере.
В IDE можно внести небольшие правки в код и быстро запустить приложение.
Создание и настройка приложения
Если вы уже работали с веб-приложениями, то структура веб-страницы вам будет знакома. Начнем с чистого HTML5+JS приложения, в котором карта отображается в теге DIV. Подключим в head страницы библиотеку PubNub.
1 |
<script src="//cdn.pubnub.com/sdk/javascript/pubnub.4.19.0.min.js"></script> |
Также нужно подключить Google Maps API через тег SCRIPT в нижней части HTML страницы.
На момент написания статьи релевантной считается версия 3.exp.
1 |
<script src="//maps.googleapis.com/maps/api/js?v=3.exp&key=YOUR_MAPS_API_KEY&callback=initialize"></script> |
Необходимо заменить плейсхолдер ключ API карты в атрибуте SCRIPT SRC.
Чтобы HTML5 локация работала, необходимо, чтобы пользователь явно разрешил доступ к локации на своем устройстве для приложения. Обработка фолбека для случая, когда доступ к локации запрещен, не входит в тему урока.
Настройки PubNub подключаются внутри простой JS карты. Можете обновить ее своими значениями:
1 2 3 4 |
var pubnub = new PubNub({ publishKey: 'YOUR_PUB_KEY', subscribeKey: 'YOUR_SUB_KEY' }); |
Запуск кода
Для запуска приложения в CodePen не нужно ничего делать – оно автоматически запускается из онлайн редактора.
В зависимости от того, где вы откроете приложение (геолокация) и возможностей сети (WiFi или LTE), вы можете увидеть разную локацию (IP или GPS локация). Мы выяснили, что у разных устройств и браузеров свои характеристики точности положения. Одни точнее, другие менее точны.
Часть 2: маркеры карты
Реализация маркеров карты для определения положения устройства на карте.
Что такое маркеры карты?
В этой части мы добавим маркеры карты в карту для мобильного приложения и веба.
С помощью маркеров определяется положение пользователя или устройства на карте. Для начала разместим на карте один маркер и случайно обновим его положение.
Если вы работали с HTML5 приложениями, структура кода должна быть вам знакома.
Начнем с чистого HTML5 приложения и подключим PubNub библиотеку для взаимодействий в реальном времени, а также Bootstrap CSS для стилей.
1 2 3 4 5 6 7 8 9 |
<!doctype html> <html> <head> <title>Google Maps Tutorial</title> <script src="//cdn.pubnub.com/sdk/javascript/pubnub.4.19.0.min.js"></script> <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" /> <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" /> </head> <body> |
Если вам интересно, где подключен Google Maps API – в самом конце HTML5 страницы. Так коду карты будет доступен весь DOM.
Создадим DIV для приложения, а внутри него еще один DIV для карты. Ширину и высоту пропишем через инлайн CSS.
В реальном приложении лучше определить стили в отдельном файле. Именно это мы имели в виду, когда говорили, что хотим подключить скрипт Google Maps после определения DOM элемента canvas.
1 2 3 4 |
<div class="container"> <h1>PubNub Google Maps Tutorial - Live Map Marker</h1> <div id="map-canvas" style="width:600px;height:400px"></div> </div> |
Осталось разобрать кучу JS кода. Давайте по порядку.
Широта/долгота
Установим первичную широту и долготу на Сан Франциско. Затем определим функцию, которая дает точку на круге, основанную на текущем времени. Определим радиус (в градусах).
Воспользуемся тригонометрией – точка на круге задается через x = «начальная долгота плюс косинус времени ввода радиуса», и y = «начальная широта плюс синус входного времени радиуса». Для удобства будем возвращать JS объект с этими значения широты и долготы.
1 2 3 4 5 6 7 8 9 |
<script> window.lat = 37.7850; window.lng = -122.4383; function circlePoint(time) { var radius = 0.01; var x = Math.cos(time) * radius; var y = Math.sin(time) * radius; return {lat:window.lat + y, lng:window.lng + x}; }; |
Сдвиг положения маркера карты
Закончили с математикой, перейдем к приятному. Определим карту и переменные для хранения карты и объектов маркеров, чтобы иметь возможность ими манипулировать налету при поступлении событий PubNub.
Затем определим колбек инициализации, который Google Maps JavaScript API может вызывать после загрузки. Чтобы колбек был доступен API, он должен принадлежать объекту window.
1 2 3 4 5 6 7 |
var map; var mark; var initialize = function() { map = new google.maps.Map(document.getElementById('map-canvas'), {center:{lat:lat,lng:lng},zoom:12}); mark = new google.maps.Marker({position:{lat:lat, lng:lng}, map:map}); }; window.initialize = initialize; |
Затем определяем обработчик события redraw, который будем вызывать при получении налету события изменения позиции.
В первой части функции устанавливаем новые значения широты и долготы из сообщения. Затем запускаем подходящие методы на объектах карты и маркера для обновления позиции и повторного центрирования карты.
1 2 3 4 5 6 |
var redraw = function(payload) { lat = payload.message.lat; lng = payload.message.lng; map.setCenter({lat:lat, lng:lng, alt:0}); mark.setPosition({lat:lat, lng:lng, alt:0}); }; |
Подключение карты к PubNub
Мы определили колбеки. Теперь у нас есть все необходимые механизмы, и мы можем перейти к инициализации функциональности PubNub стриминга данных в реальном времени.
Во-первых, необходимо определить название канала, который будет ожидать обновления позиции. Далее инициализируем библиотеку PubNub с помощью ключей публикации и подписки, которые мы настроили в части 1.
В конце мы указываем библиотеке PubNub подписку на соответствующий канал и прикрепляем функцию redraw, как обработчик входящих событий.
Вы спросите, а что создает эти события?
1 2 3 4 5 6 7 |
var pnChannel = "map-channel"; var pubnub = new PubNub({ publishKey: 'YOUR_PUB_KEY', subscribeKey: 'YOUR_SUB_KEY' }); pubnub.subscribe({channels: [pnChannel]}); pubnub.addListener({message:redraw}); |
Для этого простого урока зададим базовый JS таймер публикации новых позиций на основе текущего времени. Каждые 500 миллисекунд будем запускать анонимную колбек функцию, которая публикует новый объект с широтой/долготой (создается через вызов circlePoint()) в определенном канале PubNub.
1 2 3 4 |
setInterval(function() { pubnub.publish({channel:pnChannel, message:circlePoint(new Date().getTime()/1000)}); }, 500); </script> |
Инициализация Google Maps
Последнее, но не менее важное – инициализируем Google Maps API в самом конце, чтобы успели загрузиться DOM элементы, и выполниться предварительные условия JS.
1 2 3 |
<script src="//maps.googleapis.com/maps/api/js?v=3.exp&key=YOUR_GOOGLE_MAPS_API_KEY&callback=initialize"></script> </body> </html> |
Наше JS приложение работает, и мы можем устанавливать маркеры на карте.
Часть 3: живое отслеживание положения
Движение маркеров на карте в реальном времени на основе положения устройства.
Что такое отслеживание геолокации?
В этой части мы будем в реальном времени обновлять JS маркеры, созданные в части 2.
Будем собирать локацию пользователя с его устройства с помощью HTML5 location API, стримить и публиковать изменения локации (на основе того, как устройство само оценивает свое положение) на карту с помощью PubNub Realtime Messaging.
Разбор кода
У нас есть DIV для приложения и DIV для карты. Это мы задали в предыдущей части. Пора использовать HTML5 location API для обновления нашего положения в реальном времени.
HTML5 Location API
Давайте по порядку. Сперва мы настраиваем первичную широту и долготу на Сан-Франциско.
Затем создаем функции для получения локации устройства с помощью HTML5 location API и обновления переменных положения в браузере. Мы задали внутренний таймер для периодического получения локации устройства. Для удобства создадим возвращаемый JS объект со теми значениями широты и долготы.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<script> window.lat = 37.7850; window.lng = -122.4383; function getLocation() { if (navigator.geolocation) { navigator.geolocation.getCurrentPosition(updatePosition); } return null; }; function updatePosition(position) { if (position) { window.lat = position.coords.latitude; window.lng = position.coords.longitude; } } setInterval(function(){updatePosition(getLocation());}, 10000); function currentLocation() { return {lat:window.lat, lng:window.lng}; }; |
ОК, с HTML5 локацией разобрались. Перейдем к десерту.
Живая локация
Мы определили переменные карты и маркера для хранения объектов карты и маркера, чтобы манипулировать ими налету при поступлении событий PubNub.
Затем мы определили колбек инициализации, который Google Maps JavaScript API вызывает после загрузки и проверяет, чтобы он был в объекте window, чтобы API имел к нему доступ.
1 2 3 4 5 6 7 |
var map; var mark; var initialize = function() { map = new google.maps.Map(document.getElementById('map-canvas'), {center:{lat:lat,lng:lng},zoom:12}); mark = new google.maps.Marker({position:{lat:lat, lng:lng}, map:map}); }; window.initialize = initialize; |
Далее мы определяем обработчик события redraw, который вызываем при получении налету нового события об изменении положения. В первой части функции мы задаем новые значения широты и долготы из сообщения.
Затем запускаем подходящие методы на объектах карты и маркера для обновления положения и повторного центрирования карты.
1 2 3 4 5 6 |
var redraw = function(payload) { lat = payload.message.lat; lng = payload.message.lng; map.setCenter({lat:lat, lng:lng, alt:0}); mark.setPosition({lat:lat, lng:lng, alt:0}); }; |
Мы определили колбеки. Теперь у нас есть все необходимые механизмы, и мы можем перейти к инициализации функциональности PubNub стриминга данных в реальном времени.
Во-первых, необходимо определить название канала, который будет ожидать обновления позиции. Далее инициализируем библиотеку PubNub с помощью ключей публикации и подписки, которые мы настроили в части 1.
В конце мы указываем библиотеке PubNub подписку на соответствующий канал и прикрепляем функцию redraw, как обработчик входящих событий. Вы спросите, а что создает эти события? Читайте дальше!
1 2 3 4 5 6 7 |
var pnChannel = "map2-channel"; var pubnub = new PubNub({ publishKey: 'YOUR_PUB_KEY', subscribeKey: 'YOUR_SUB_KEY' }); pubnub.subscribe({channels: [pnChannel]}); pubnub.addListener({message:redraw}); |
Публикация широты/долготы
Для этого простого урока зададим базовый JS таймер публикации новых позиций на основе текущего времени. Каждые 5000 миллисекунд будем запускать анонимную колбек функцию, которая публикует новый объект с широтой/долготой (создается через вызов currentLocation ()) в определенном канале PubNub.
1 2 3 4 |
setInterval(function() { pubnub.publish({channel:pnChannel, message:currentLocation()}); }, 5000); </script> |
Последнее, но не менее важное – инициализируем Google Maps API в самом конце, чтобы успели загрузиться DOM элементы, и выполниться предварительные условия JS.
1 2 3 |
<script src="//maps.googleapis.com/maps/api/js?v=3.exp&key=YOUR_GOOGLE_MAPS_API_KEY&callback=initialize"></script> </body> </html> |
Часть 4: маршруты полета
Показывает маршрут, который проделало устройство, рисуя след позади маркера.
Что такое маршруты полета?
В этом уроке добавим маршруты полета через Polylines. Они позволяют динамически рисовать обновленные пути по заданным пользователем точкам на карте в вебе или мобильном браузере.
Для демо разместим один polyline и обновим его конечную точку налету на основе случайного положения внутри границы.
Обзор кода
Мы настроили DIV для приложения и DIV для карты в предыдущем уроке. Теперь добавим маршруты полета. Приступим к делу.
Определим переменные map, mark и lineCoords для хранения объектов карты, маркера и координат polyline , чтобы манипулировать ими налету при поступлении событий PubNub.
Затем мы определили колбек инициализации, который Google Maps JavaScript API вызывает после загрузки и проверяет, чтобы он был в объекте window, чтобы API имел к нему доступ.
1 2 3 4 5 6 7 8 |
var map; var mark; var lineCoords = []; var initialize = function() { map = new google.maps.Map(document.getElementById('map-canvas'), {center:{lat:lat,lng:lng},zoom:12}); mark = new google.maps.Marker({position:{lat:lat, lng:lng}, map:map}); }; window.initialize = initialize; |
Широта/долгота
Далее мы определяем обработчик события redraw, который вызываем при получении налету нового события об изменении положения. В первой части функции мы задаем новые значения широты и долготы из сообщения.
Затем запускаем подходящие методы на объектах карты, маркера и polyline для обновления положения, добавления его в конец линии и повторного центрирования карты.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
var redraw = function(payload) { lat = payload.message.lat; lng = payload.message.lng; map.setCenter({lat:lat, lng:lng, alt:0}); mark.setPosition({lat:lat, lng:lng, alt:0}); lineCoords.push(new google.maps.LatLng(lat, lng)); var lineCoordinatesPath = new google.maps.Polyline({ path: lineCoords, geodesic: true, strokeColor: '#2E10FF' }); lineCoordinatesPath.setMap(map); }; |
Инициализация PubNub
Мы определили колбеки. Теперь у нас есть все необходимые механизмы, и мы можем перейти к инициализации функциональности PubNub стриминга данных в реальном времени.
Во-первых, необходимо определить название канала, который будет ожидать обновления позиции. Далее инициализируем библиотеку PubNub с помощью ключей публикации и подписки, которые мы настроили в части 1.
В конце мы указываем библиотеке PubNub подписку на соответствующий канал и прикрепляем функцию redraw, как обработчик входящих событий. Вы спросите, а что создает эти события? Читайте дальше!
1 2 3 4 5 6 7 |
var pnChannel = "map3-channel"; var pubnub = new PubNub({ publishKey: 'YOUR_PUB_KEY', subscribeKey: 'YOUR_SUB_KEY' }); pubnub.subscribe({channels: [pnChannel]}); pubnub.addListener({message:redraw}); |
Публикация широты/долготы
Для этого простого урока зададим базовый JS таймер публикации новых позиций на основе текущего времени. Каждые 500 миллисекунд будем запускать анонимную колбек функцию, которая публикует новый объект с широтой/долготой (движение на северо-восток) в определенном канале PubNub.
В приложении, скорее всего, вы получите позицию в реальном времени или позицию пользователя.
1 2 3 4 |
setInterval(function() { pubnub.publish({channel:pnChannel, message:{lat:window.lat + 0.001, lng:window.lng + 0.01}}); }, 500); </script> |
Последнее, но не менее важное – инициализируем Google Maps API в самом конце, чтобы успели загрузиться DOM элементы, и выполниться предварительные условия JS.
1 2 3 |
<script src="//maps.googleapis.com/maps/api/js?v=3.exp&key=YOUR_GOOGLE_MAPS_API_KEY&callback=initialize"></script> </body> </html> |
Можете гордиться, мы закончили!
PubNub и Google Maps API отлично работают вместе. Google Maps предоставляет мощные функции с картами, а PubNub подключает их к устройствам в реальном времени.
Автор: Joe Hanson
Источник: //hackernoon.com/
Редакция: Команда webformyself.