Картографія у вебі: просто, зручно, елегантно

Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті.

Доброго дня, дорогий читач! Мене звати Володимир Шалата. Я працюю Front-end розробником у компанії Intellias останні 2 роки, маю за плечима вже більше 7 років досвіду як інженер-розробник. Сьогодні я розповім про картографію у вебі: про труднощі, деталі, та приклади із реальних проєктів.

Ця стаття може бути цікавою як для розробників, які вже стикалися з картографією і можуть почерпнути щось нове для себе, так і для девелоперів, які ще не пробували себе в цьому, але хочуть розібратися, як почати роботу з картами у вебі та які інструменти доступні при роботі з ними.

Більшість із нас має уявлення про вигляд Землі ще зі шкільних років. Ви точно пригадаєте розгорнуте зображення континентів у форматі А4 на контурних картах або в атласі. Цього достатньо, щоб зрозуміти базову модель Землі та побачити, що Америка — це два континенти, а Австрія та Австралія — це не одне і те ж :) Проте, справжні труднощі виникають тоді, коли перед нами виникає завдання поєднати математичну модель із реальною географією. Якщо нам потрібна точність з допустимою похибкою 0,5-1%, то базова модель зі шкільного атласу нас не задовольнить. Подивіться лишень, як змінюються розміри Антарктиди чи Гренландії, якщо перенести їх реальні розміри ближче до екватора.

Більш реалістичним уявленням про Землю є її зображення у вигляді сфероїду, геоїду, або ж так званого «земного еліпсоїду». Яке б визначення ми не обрали, важливо зрозуміти, що представити Землю як математичну модель з точними обчисленнями — це непросте завдання.

Проєкції

Загалом існує величезна кількість проєкцій, але поговорімо лише про деякі з них. Перша — це циліндрична система координат. Вона доволі проста, але в той же час достатньо продумана. У цій моделі відстані між меридіанами чи широтами завжди однакові. Вона є швидше демонстративною і використовується зокрема в NASA WorldWind.

Наступна система — циліндрична рівнокутна. Це класична система, яку розробив Герард Меркатор для застосування у своєму атласі, і вона є однією з найбільш поширених. ЇЇ суть полягає у тому, що при наближенні до південного чи північного полюсів відстані між лініями збільшуються. Відповідно, є певна похибка зображення, але з точки зору кутового співвідношення, ця схема є більш реалістичною.

Наступна система — геоцентрична сферична. Тут фігурують три значення: r — це відстань від початку системи координат до нашої безпосередньої точки та два кути. Суть у тому, що ми представляємо Землю як тривимірну площину x,y,z. Тут xy — це площина, яка проходить через лінію екватора, а xz — це площина, яка проходить через меридіан. Фактично кожну точку можна представити через цю відстань r та два кути: θ і φ. Відповідно кут θ — це кут відхилення нашої точки від площини xy, він фактично відповідає за довжину, а кут φ відповідає за відхилення точки від площини yz, тобто відповідає за значення довготи.

Основна система, яка використовується у переважній більшості вебзастосунків, — це Web Mercator Projection. Вона є швидше циліндричною, однак, її можна вважати компромісною, тому що вона використовує кращі сторони циліндричної та частково сферичної систем. Її можна побачити у Google Maps, OpenStreetMap, Mapbox, Bing Maps, MapQuest тощо. Вона є стандартом сучасної онлайн-картографії. Хоча навіть до її точності є зауваження, які, наприклад, наводить Американське національне агентство геопросторової розвідки. Але для того, щоб привести нас з точки А в точку В із точністю до декількох метрів, цієї моделі достатньо.

Мапи у вебі

Розібравшись із математичною складовою мап, перейдемо до роботи мап у вебі. Спочатку розділимо їх на дві групи — растрові та векторні.

У растрових мапах малювання нового контенту відбувається на основі завантажених, наперед заготовлених, порізаних зображень із сервера.

Натомість у векторних мапах ми отримуємо набір команд, який передається або у WebGL, або для малювання на нативних пристроях.

Растрові мапи

Основний принцип роботи растрових мап — це розділення зображення карти на тейли (від англ. «плитка», «частинка»), таким чином, щоб для кожного рівня приближення завантажувалися тільки необхідні тейли із заданим рівнем точності. У растрових мапах малювання та нарізка відбуваються на стороні сервера. Клієнт у цьому випадку тільки збирає та правильно склеює ці тейли.

Однак, виникає питання: «Як клієнтське API визначає, які плитки потрібно завантажити з сервера?». Розглянемо цей процес детальніше. Наприклад, ми отримали з Back-end точку з координатами широти та довготи. Щоб правильно показати цю точку на мапі, API потрібно зробити декілька кроків.

Крок 1: перевести набір координат у світові координати згідно з проєкцією Web Mercator. Уявімо, що на рівні масштабу 0 наша мапа — це одна плитка базового розміру. Світова координата — це таке значення з плаваючою точкою, яке вимірюється від початку проєкції карти до конкретного місця. Розмір плитки — 255 на 255 пікселів в сторону x і y. Отже, світова координата матиме абсолютне значення, і, фактично, корисний простір цього набору координат становить від 0 до 256 пікселів.

Крок 2: визначити піксельні координати відносно світових. Піксельні координати — це відносне значення, воно залежить від світових координат та поточного рівня приближення. Уявімо, що світова координата — це дротик, який потрапив у певну точку. Для того, щоб дізнатися, які ділянки навколо цієї точки треба завантажити, нам потрібен рівень приближення. Отже, координати пікселя будуть змінюватися відповідно до рівня приближення.

Крок 3: визначити всі тейли карти, які лежать у межах заданого пікселя. Тейли формуються так же, як і світові координати, тобто починаючи з верхнього лівого кута у бік осі xy збільшується порядок розташування тейлів.

Крок 4: конвертувати з координат пікселів координати тейла, які нам необхідні, та зробити запит на сервер на їх отримання. API карт фактично витягує не тільки ті плитки, на які вказує конкретний піксель, а ще й сусідні тейли, щоб вони потрапили у вікно користувача і щоб не було прогалин в UX.

Векторні мапи

Векторні мапи малюються на стороні клієнта. Це також відбувається за допомогою тейлів, але цього разу векторних.

Переваги векторних мап:

  • Висока чіткість зображення.
  • Можливість додавати 3D-моделі будівель із високим рівнем деталізації.
  • Програмне управління нахилом і курсом.
  • Покращене управління камерою та функція дробового масштабу.
  • Плавне масштабування та якісний UX.

За допомогою векторних мап ми також можемо додавати кастомні елементи. Наприклад, у застосунках Uber, Uklon чи Glovo можна побачити, як 3D-точка рухається по мапі в режимі реального часу. Ще одна крута можливість — це додавання відео на мапу. Наразі також розпочалися розробки по підтримці віртуальної реальності у браузері. У майбутньому ми матимемо можливість поєднати віртуальну реальність і картографію, щоб надати користувачам цікавий та незрівнянний UX.

Як можна додати мапу в застосунок

Імплементація мапи починається зі створення Map ID у консолі розробника. Тут можна обрати растрові або векторні мапи та різні додаткові опції (кут нахилу тощо). Далі ми можемо покращити мапу, додавши унікальну кольорову гаму або обравши темну тему, яка наразі є досить популярною.

Через консоль розробника можна змінити практично будь-яку частинку, що показується на мапі: назви країн, вулиць, колір води, гір тощо. Скажімо, можемо змінити колір води у Дніпрі, щоб він відповідав реальній ситуації з забрудненням.

Останній крок перед імплементацією — це створення API-ключа. Для цього потрібно увімкнути Maps JavaScript API, зайти в розділ Credentials і створити нові облікові дані (credentials). Підключення самих мап може відбуватися у два способи: через тег <script> напряму або через <iframe>.

Як налаштовувати та змінювати мапи

Можна виділити чотири види об’єктів, які можна використовувати, малюючи на картах: маркери, лінії, кластери та фігури. Фігури також можна поділити на чотири підкатегорії: трикутники, квадрати, круги та полігони.

Маркери

Для створення маркерів існують стандартні кроки. Вам потрібно викликати конструктор та додати набір параметрів. Іконку маркера можна змінити, задати розміщення, анімацію тощо.

new gmapApi.Marker({
    animation: gmapApi.Animation.DROP,
 
    map: googleMapsInstance,
    position: { lat: 35.111, lng: 45.222 },
    icon: { url: 'path/image', anchor: { x: 15, y: 15 },
});

Лінія

Лінії створюються за тим самим принципом, що і маркери. Потрібно створити новий об’єкт, передати йому набір параметрів: довжину лінії, її колір та шлях, тобто декілька точок, через які вона проходить.

new gmapApi.Polyline({
    path: [
          { lat: 48.864, lng: -66.678 },
          { lat: 38.123, lng: -76.098 }  
    ],
    map: googleMapsInstance,
    strokeColor: 'red',
    strokeOpacity: 1,
    strokeWeight: 2,
});

Кластери

Якщо ви користувалися різними сервісами прокату самокатів, то напевне стикалися з цими двома різними картинками. Деякі застосунки показують усі вільні самокати, що розташовані на невеликій ділянці (зображення праворуч). Інші застосунки ховають усі точки та надають кластеризацію (зображення ліворуч).

Кластеризація працює так, що при наближенні з кластерів, розкривається певний набір іконок. Можна приближувати до того моменту, допоки розмір кластера не досягне свого кінцевого значення. Таким чином можна замінити малювання величезної кількості точок на один кластер.

В іншому випадку, якщо малювати десятки тисяч точок, то можна навантажити браузер роботою на декілька секунд, а можна взагалі заставити його повиснути. Тому Google мапи мають простий API, який вмикає кластеризацію. Для цього потрібно створити новий об’єкт кластера й передати в нього вже створену карту, маркери та зображення для самих кластерів.

new MarkerClusterer(
googleeMapInstance, 
markers,
 { imagePath: '<a href="https://path-to-your-image">https://path-to-your-image</a>' }
);

Фігури: полігони та круги

Полігони та круги — це складні фігури. За їхнє малювання відповідає бібліотека drawing. Щоб її підключити, потрібно вказати цей параметр під час запиту на отримання карт. У drawing manager є два основні стани: drawingControl true або false. Відповідно, при значенні true — використовується UI за замовчуванням, не надто красивий, але достатній, щоб почати роботу з графікою.

new google.maps.drawing.DrawingManager({
    drawingControl: true,
    map: googleMapsInstance,
    drawingControlOptions: {
        drawingModes: [
            google.maps.drawing.OverlayType.MARKER,
            google.maps.drawing.OverlayType.CIRCLE,
            google.maps.drawing.OverlayType.POLYGON,
        ],
    },
    polygonOptions: { ...polygonDrawingOptions },
    circleOptions: { ...circleDrawingOptions },
});

При значенні false ми переходимо у режим програмного управління процесом. Це дозволяє нам робити настільки підходящий і потужний UI, наскільки це необхідно в нашому застосунку, адже отримаємо контроль на всією гамою можливостей API.

new google.maps.drawing.DrawingManager({
    drawingControl: false,
 map: googleMapsInstance,
    drawingControlOptions: {
        drawingModes: [
            google.maps.drawing.OverlayType.MARKER,
            google.maps.drawing.OverlayType.CIRCLE,
            google.maps.drawing.OverlayType.POLYGON,
        ],
    },
    polygonOptions: { ...polygonDrawingOptions },
    circleOptions: { ...circleDrawingOptions },
});

Висновок

Робота з картами у вебі може бути не тільки складною, але й цікавою. Вона відкриває розробникам багато можливостей робити UI більш зручним, а також враховувати потреби користувача.

При цьому, варто зважати не тільки на можливості, але й на цінову політику. До прикладу, Google Maps — дуже потужний інструмент, але і ціна на нього за останні декілька років піднялася в рази. Як альтернативу можна розглянути OpenStreetMap, з його безкоштовним сервером набору тейлів та вільною ліцензією на використання. Проте, зрозуміло, що набір функціоналу буде меншим, аніж в Google Maps API.

Кінцеве рішення про використання того чи іншого сервісу має базуватися, перш за все, на проблемі, котру нам як розробникам потрібно вирішити, а також, звичайно, ціновій політиці компанії.

👍НравитсяПонравилось7
В избранноеВ избранном2
LinkedIn
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Стаття сподобалась, проблем з форматуванням не помітив.

Жаль тільки автор не відповідає по суті статті

За допомогою векторних мап ми також можемо додавати кастомні елементи.

В браузери почали нормально підтримувати вектор на рівні canvas?
Швидкий гуглінг показав, що канвас->webgl лідує

Наприклад, у застосунках Uber, Uklon чи Glovo можна побачити, як 3D-точка рухається по мапі в режимі реального часу.

Не розумію, як це до вектору відноситься — це робиться і на канвасі нормально (чи навіть на хтмл)

І які там обмеження на google maps для бізнесу?

PS:

OpenStreetMap

cowards
Вони неправильно відповідають на питання «чий Крим»

А в чому проблема малювати векторні елементи в canvas? Автор мав на увазі векторні мапи, які рендеряться на стороні клієнта, а не отримуються з сервера в растровому вигляді, як тайли.
Canvas це растровий шар, як і монітор компʼютера, але це не означає шо він не може відображати векторну графіку.

А я мав на увазі векторні мапи які будуть рендеритись на відеокарті без участі канвас

А може фахівець вашого рівня вибрати правильне форматування для прикладів коду?

А що не так із форматуванням? Це ж кажись JavaScript. Тут немає «правильного» форматування.

<div class="hl-wrap javascript"><pre>
(function (){
    console.log("Привіт Світ!");
})(); 
</pre></div>

Придивіться до підсвічування та форматування коду в статті.

Підсвітка це діло смаку. Деякі з відомих розробників її взагалі не використовують.
В мене звичайно не вбудований голову JavaScript лінтер, але на перший погляд з форматуванням там ніби все норм. Принаймні воно не заважає розумінню прикладів коду.

Дякую за заваження Ярослав! Це як мінімум означає що код був прочитаний. Є питання до підсвітки коду, думаю що копірайтери котрі готували до публікації могли використовувати різні редактори коду, і як наслідок — різний колір.

думаю що копірайтери котрі готували до публікації могли використовувати різні редактори коду

Ви як автор можете передивитись статтю до публікації і навіть виправити помилки після редакторів та навіть зараз можете виправити форматування.

Подписаться на комментарии