Статьи

Создание великолепных 3D-карт с eegeo.js и Leaflet

eegeo.js — это API-интерфейс для создания трехмерных карт с открытым исходным кодом, созданный на основе популярной библиотеки картографии Leaflet .

Существует множество картографических библиотек, которые позволяют встраивать или создавать простые 2D-карты. В частности, Google Maps , Bing Maps , ЗДЕСЬ , Mapbox и OpenStreetMap . Популярные библиотеки абстракции картографирования, такие как OpenLayers и Leaflet, также позволяют изменять базовый уровень карты без необходимости изменять логику приложения.

В связи с тем, что использование API Google Планета Земля перешло к устареванию безопасности NPAPI , выбор API трехмерных карт ограничен. Существуют альтернативы, такие как популярная библиотека Цезия . eegeo.js — это еще одна, обеспечивающая динамичную, по-настоящему цельную трехмерную карту мира, от космоса до стола на внутренней карте. Прямо в браузере с помощью WebGL.

eeGeo 3D Maps Space to Desk

Начиная

В этой статье я покажу вам, как просто встроить великолепную 3D-карту Лондона и добавить некоторые базовые функциональные возможности с помощью API транспорта для Лондона .

Спойлер: 3D-карты так же просты, как и использование 2D-карт.

Отказ от ответственности: я занимаюсь разработкой программного обеспечения SVP в eeGeo, и у меня есть контроль над развитием eegeo.js

Существует множество руководств по использованию Leaflet. eeGeo.js был сознательно построен поверх Leaflet, чтобы разработчики, уже знакомые с Leaflet, могли сразу же начать работу. Я полностью рекомендую Leaflet примеры и документацию .

В этой статье будут рассмотрены основные понятия HTML, CSS, JavaScript и простые способы отображения.

Что вам нужно

Эта статья будет охватывать несколько ключевых компонентов:

Отображение 2D карты Лондона

Во-первых, давайте создадим 2D-карту Лондона, используя Leafet и Open Street Map. Листовка супер простая. Все, что вам нужно, это небольшой кусочек HTML для настройки страницы, <div> для размещения вашей карты и несколько строк JavaScript для создания и установки начальной позиции.

Создать HTML

Давайте создадим HTML-файл со следующей разметкой:

 <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Building Gorgeous 3D maps with eegeo.js and Leaflet</title> </head> <body> <div id="map" style="width: 600px; height: 400px;"></div> </body> </html> 

Включить буклет

Включить Leaflet так же просто, как добавить библиотеку JavaScript Leaflet и CSS. Включите их в <head> :

 <link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" /> <script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script> 

Добавить буклет JavaScript

Следующие строки JavaScript инициализируют Leaflet и используют OpenStreetMap в качестве слоя листов. Вы можете добавить это как внешний файл JavaScript или для простоты в блоке <script></script> ниже <div id="map"/> :

 var map = L.map('map', { center: [51.517327, -0.120005], zoom: 15 }); L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', { attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors' }).addTo(map); 

Код инициализирует карту с центром на станции метро Holborn на WGS84, широта в десятичных градусах, долгота 51.517327, -0.120005 . Вы можете получить эти координаты, щелкнув правой кнопкой мыши и выбрав «Что здесь» на цифровых картах, таких как maps.eegeo.com или Google Maps . Позже вы увидите, что большинство геопространственных API возвращают позиции в стандартных десятичных градусах широты и долготы WGS84, включая API TfL.

Запустите 2D карту

Загрузите ваш HTML где-нибудь или просмотрите его локально. Я рекомендую не загружать напрямую из файловой системы, а использовать локальный петлевой веб-сервер. Сохраните ваш HTML как index.html и в той же папке выполните: python -m SimpleHTTPServer 8000 вы можете зайти на http://localhost:8000/ в вашем браузере.

Вы увидите следующую карту с центром на станции метро Holborn в Лондоне:

2D карта Лондона с центром на станции метро Holborn

Отображение 3D-карты Лондона

Поскольку eeGeo.js построен поверх Leaflet, очень мало нужно сделать, чтобы превратить 2D-карту Лондона в великолепную 3D-карту.

Измените JavaScript, который мы добавили выше, который читается как var map = L.map ... следующим образом. Требуется бесплатный ключ API eeGeo . Вы также должны удалить JavaScript, который вызывает L.tileLayer как он больше не требуется.

JavaScript должен теперь читать:

 var map = L.eeGeo.map('map', '<your_api_key>', { center: [51.517327, -0.120005], zoom: 15 }); 

Измените <script> include, который мы добавили в <head> чтобы включить eegeo.js вместо Leaflet. Файл eegeo.js уже содержит Leaflet, поэтому не включайте оба:

 <script src="https://cdn-webgl.eegeo.com/eegeojs/api/v0.1.780/eegeo.js"></script> 

Вот и все! Изменив всего пару линий, вы увидите точно такой же вид на станцию ​​метро Holborn, но в великолепном 3D:

eeGeo.js 3D-карта Лондона вокруг станции метро Holborn

Изменение масштаба, наклона и ориентации

Так как eeGeo.js полностью 3D, можно вращать и наклонять карту. setView функция setView Leaflet с необязательными аргументами наклона и заголовка для поддержки трехмерного поведения карты.

Добавьте следующий JavaScript и через 10 секунд карта будет плавно анимироваться в 3D от станции метро Holborn до корнишона в Лондоне:

 setTimeout(function() { map.setView([51.514613, -0.081019], 17, {headingDegrees: 204.374, tiltDegrees:15.0}); }, 10000); 

eeGeo.js 3D карта корнишона, Лондон

На скриншоте не видно взаимодействия, но этот CodePen показывает анимацию в действии:

Дополнительные аргументы для setView() выше:

поле Тип Описание
headingDegrees десятичная дробь десятичные градусы с севера по часовой стрелке, где 0,0 — север.
tiltDegrees десятичная дробь угол наклона в градусах, где 45.0 — это прямой заголовок, а 0.0 — наклонный вид по умолчанию

Взаимодействие с 3D-картой Лондона

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

Чтобы добавить маркер на станции метро Holborn на карту, вызовите L.marker() :

 L.marker([51.517327, -0.120005]).addTo(map); 

Чтобы добавить полигон на площади Рассела, вызовите L.polygon() . Полигон определяется четырьмя вершинами по часовой стрелке, начиная с перекрестка Бернард Сент-Уолборн-Плейс в северном восточном углу площади Рассела:

 L.polygon([[51.522771, -0.125772], [51.521520, -0.124192], [51.520631, -0.126358], [51.521963, -0.127895]]).addTo(map); 

Добавить полилинию маршрута через Блумсбери, начиная с Грейт-Джеймс-стрит и заканчивая на Музей-стрит .:

 L.polyline([[51.521788, -0.117101], [51.520732, -0.116524], [51.520430, -0.117641], [51.519873, -0.119602], [51.519034, -0.120993], [51.518784, -0.121537], [51.517265, -0.125088], [51.516257, -0.124466]]).addTo(map); 

Обновите, и три примитива Leaflet теперь будут отображаться на карте:

eeGeo.js 3D-карта, показывающая маркер, полилинию и многоугольник

Вы заметите, что вызовы L.marker() , L.polyline() и L.polygon() являются вызовами Leaflet API. Если мы вернем карту обратно в OpenStreetMap с более ранних версий, те же самые вызовы будут работать на базовом уровне 2D OSM:

2D OpenStreetMap с маркером, ломаной линией и полигоном

API транспорта для Лондона (TfL)

Далее, давайте добавим некоторые данные из реального API на 3D-карту Лондона.

API транспорта для Лондона (TfL) большой и сложный. Он охватывает весь транспорт в Лондоне, включая автобус, метро, ​​наземный транспорт, прокат велосипедов и предоставляет данные о состоянии и времени прибытия в режиме реального времени.

Сфера действия полного API TfL слишком велика, чтобы охватить эту статью. Я сосредоточусь исключительно на очень небольшом количестве конечных точек API, которые описывают лондонское метро, ​​а именно:

  • Каковы доступные линии труб?
  • На каких станциях останавливается конкретная трубка?
  • Что такое «доска прибытия» конкретной станции метро?

API TfL можно использовать без ключа API со строгим ограничением скорости. Если вы используете TfL API в реальном, производственном развертывании, вы должны зарегистрировать ключ API .

Каковы доступные линии труб?

Чтобы ответить на вопрос «Что такое доступные трубные линии», API TfL предоставляет конечную точку на ресурсе Line

Нас интересует только вид транспорта «пробка», поэтому делаем следующий звонок:

 curl -v https://api.tfl.gov.uk/line/mode/tube 

возвращает ответ JSON с массивом объектов Line. Нас интересует только свойство id каждой записи:

 [{ "id": "bakerloo", "name": "Bakerloo", "modeName": "tube", "disruptions": [], "lineStatuses": [], "routeSections": [], ... },...] 

Чтобы упростить взаимодействие с TfL API, мы будем использовать jQuery, но зависимость от jQuery совершенно необязательна. Следующий JavaScript вызывает конечную точку Line и собирает идентификаторы Line:

 $.getJSON( "https://api.tfl.gov.uk/line/mode/tube", function(data) { var lines = []; $.each(data, function(k, line) { lines.push(line.id); }); }); 

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

Моделирование лондонского метро в виде графика

Вы можете думать о лондонском метро как о графике . График содержит вершины и ребра. Что касается лондонского метро, ​​я буду считать, что станции — это вершины, а линии труб образуют края.

Разрез диаграммы лондонского метро

Смоделировав центральную линию (красным цветом вверху) в виде графика, на Северном Актоне, Западном Актоне и Хангер-лейн были бы вершины. Поскольку на центральной линии к западу от Северного Актона есть ветвь, между Северным Актоном и Западным Актоном существует также центральная линия Край, а также между Северным Актоном и Хангер-лейн.

Дальше на восток по центральной линии находятся ворота Ноттинг Хилл. Есть только одна станция метро Notting Hill Gate, но у нее есть платформы для трех линий: центральная (красная), круговая (желтая) и районная (зеленая). Мы хотим добавить только один маркер Leaflet для Notting Hill Gate, а не три. Если мы смоделируем Ноттинг-Хилл-Гейт в качестве вершины, то будет центральная линия Edges (до Holland Park и Queens Way), окружная линия и районная линия Edges до Bayswater и High Street Kensington.

Это важно, так как TfL API моделирует Underground как ориентированный граф .

Какие станции на конкретной линии метро?

Теперь у нас есть идентификатор линии каждой линии подполья. Я также планирую свободно моделировать станции и линии в виде вершин и ребер на графике. Учитывая идентификатор линии, API TfL может затем сказать нам, на каких станциях останавливается каждая линия. API TfL именует их как StopPoints . Конечной точкой, которую мы будем называть, является Линия, Маршрут, включающий последовательность СтопПоинтов.

Давайте сделаем еще один вызов API TfL, чтобы описать исходящий маршрут центральной линии:

 curl -v https://api.tfl.gov.uk/line/central/route/sequence/outbound 

Это возвращает очень большую полезную нагрузку JSON, более 8000 красивых печатных строк. К счастью, нас интересует stopPointSequences ключ stopPointSequences :

 "stopPointSequences": [ { "lineId": "central", ... "stopPoint": [ ... { "id": "940GZZLUNHG", "name": "Notting Hill Gate Underground Station", ... "lat": 51.509128, "lon": -0.196104 }, { "id": "940GZZLUQWY", "name": "Queensway Underground Station", ... "lat": 51.510312, "lon": -0.187152 }, ... ], }, ... ] 

Это свойство представляет собой список объектов JSON, которые группируют линию в непрерывные секции. Внутри StopPointSequence находятся все StopPoints по порядку вдоль линии.

Следующий JavaScript обрабатывает создание уникальных станций, а также создание полилиний, чтобы мы могли нарисовать линию для краев линий трубки.

 var stopPoints = {}; $.getJSON( "https://api.tfl.gov.uk/line/central/route/sequence/outbound", function( data ) { var lineSegments = []; $.each(data.stopPointSequences, function(k, v) { var line = []; $.each(v.stopPoint, function(k, sp) { line.push([sp.lat, sp.lon]); if (!(sp.id in stopPoints)) { stopPoints[sp.id] = {"id":sp.id, "name":sp.name, "lat":sp.lat, "lon":sp.lon}; } }); lineSegments.push(line); }); }); 

Теперь мы можем вызвать вышеуказанный JavaScript для каждой строки Underground. После этого в словаре stopPoint будут собраны все уникальные станции. Для каждой линии у нас также есть коллекция полилиний, представляющих сечения линии трубки в массиве lineSegments .

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

Какие поезда прибывают на конкретную станцию?

Последняя конечная точка API TfL, которая нам нужна, — это живые поступления В приведенном выше разделе мы видим, что станция имеет уникальный идентификатор в API. Для Ноттинг Хилл Гейт, идентификатор 940GZZLUNHG :

 { "id": "940GZZLUNHG", "name": "Notting Hill Gate Underground Station", ... "lat": 51.509128, "lon": -0.196104 } 

Теперь мы можем вызвать API TfL StopPoint , предоставив идентификатор StopPoint:

 curl -v https://api.tfl.gov.uk/stoppoint/940GZZLUNHG/arrivals?mode=tube 

Это возвращает массив поступлений:

 [{ ... "naptanId": "940GZZLUNHG", "stationName": "Notting Hill Gate Underground Station", "lineId": "central", "platformName": "Eastbound - Platform 3", "direction": "outbound", ... "destinationName": "Epping Underground Station", "timeToStation": 290, "currentLocation": "Between White City and Shepherd's Bush", "towards": "Epping", ... }, ...] 

Это указывает на то, что поезд восточного направления до Эппинга прибудет на платформу 3 менее чем через 5 минут (290 секунд).

Положить его вместе

До сих пор я показал вам, как:

  • Создайте простую 2D карту OpenStreetMap с помощью Leaflet
  • Превратите эту простую 2D-карту в великолепную 3D-карту с eeGeo.js и Leaflet
  • Добавьте простые детали к картам в виде маркеров листов, полилиний и полигонов
  • Выполните базовые взаимодействия с API транспорта для Лондона

Теперь, чтобы объединить эти простые концепции для создания трехмерной интерактивной карты Лондона, показывающей линии и станции лондонского метро и время прибытия в реальном времени для всех станций!

3D-карта Лондона со станциями метро и временем прибытия, отображаемым в виде наложения

Добавить маркеры для станций метро

В предыдущем вызове $.getJSON() который запрашивает https://api.tfl.gov.uk/line/central/route/sequence/outbound , вызовите L.marker() для каждой станции:

 $.each(stopPoints, function(k, sp) { L.marker([sp.lat, sp.lon], { title: sp.name, options: {"id":sp.id, "name":sp.name} }).addTo(map); }); 

Мы прошли дополнительные «опции» через маркер. Это так позже, когда мы обрабатываем события при наведении мыши, мы знаем, над каким идентификатором и именем станции мы находимся.

Добавить полилинии для линий метро

Опять же, в предыдущем Ajax-вызове, который запрашивает https://api.tfl.gov.uk/line/central/route/sequence/outbound , добавьте L.polyline() для каждого сегмента линии:

 $.each(lineSegments, function(k, ls) { L.polyline(ls, {weight:8, color:"#CC3333"}).addTo(map); }); 

Цвет выше может быть получен из поиска по идентификатору линии. В этом случае у меня есть жестко закодированная круговая линия красного цвета в соответствии с Руководством по проектированию TfL

Обработка событий наведения мыши на маркерах Leaflet

Я хотел бы отображать информацию о прибытии в реальном времени из TfL API. Возможно получить обратный вызов, когда маркер листовки наведен поверх. Также возможно показать всплывающее окно Leaflet, чтобы показать название станции.

 $.each(stopPoints, function(k, sp) { var marker = L.marker([sp.lat, sp.lon], { title: sp.name, options: {"id":sp.id, "name":sp.name} }).addTo(map); marker.bindPopup(sp.name); marker.on('mouseover',_hovercard.overstation); marker.on('mouseout',_hovercard.outstation); }); 

В более сложном CodePen ниже я покажу, как обратные вызовы _hovercard. * Будут отправлять запросы в API TfL и заполнять карту выноски сообщениями о прибытии на станцию ​​в реальном времени.

Собираем все вместе

С некоторым дополнительным разделением проблем и улучшенным моделированием вы можете увидеть полную демонстрацию eegeo.js, Leaflet и TfL API в этом Code Pen:

3D-карты не должны быть трудными

В этой статье я показал, как добавить 2D-карты на ваш сайт с помощью JavaScript и Leaflet, а также как добавить простые функции карты, такие как маркеры, полилинии и полигоны. Затем я показал, как можно легко добавлять данные из реальных API, таких как API транспорта для Лондона (TfL).

Я подчеркнул преимущества кодирования по сравнению с библиотеками абстракции для отображения, такими как OpenLayers и Leaflet . Визуальные элементы вашей карты могут кардинально измениться, практически не меняя код. Я также показал, насколько простым 3D-картированием может быть использование eegeo.js .

Если у вас есть какие-либо комментарии или вопросы о чем-то в этой статье, пожалуйста, дайте мне знать в комментариях ниже.