Привет, Хабр.
Сегодня я расскажу, как можно эффективно загрузить большое количество точек на карту (веб или в мобильных приложениях).
Quick Dive
С точки зрения большинства современных картографических решений можно выделить несколько базовых подходов к отрисовке карты:
- растровый (статичные файлы — картинки с тайлами, хранящиеся на CDN и имеющие свой TTL)
- векторный
Тут нужно сделать ремарку, тайл, для тех кто не вкурсе, это специальная блочная координатная сетка (параллельно тайлами называются и статичные изображения), которая характеризуется тремя координатами (z — зум, x, y), на каждом уровне количество тайлов
Наиболее интересным на сегодняшний день является векторный формат.
Почему? Собственно, нужно начать с проблем, связанных с растровым форматом:
- Дискретные уровни зума (от 0 до 20 в большинстве случаев)
- Жёсткая привязка стилистики и данных на тайловых слоях
- Классические недостатки растра
Какие перспективы предлагает векторный формат? Собственно, их несколько:
- Зум не связан чётко с тайлами на определённом слое, а может меняться с любой точностью и плавностью
- Поскольку зачастую именно клиент (не рассматривая вариант промежуточного рендера) рендерит карту, то именно он определяет какие данные и в каком стиле он хочет отрисовывать
- Отличное качество в независимости от разрешения и т.д., что в общем-то классическое преимущество вектора над растром
Собственно всё с векторным форматом хорошо, но есть и свои недостатки. Как минимум, векторный формат сложнее кэшировать, это не так очевидно, как в большинстве случаев с растровым форматом, где достаточно предгенерированные тайлы сложить на CDN, настроить TTL и перегенерацию и больше не думать об этом.
В общем, рассказывать об этом можно очень долго, моя задача была в том, чтобы дать краткое описание собственно механизмов работы, теперь мы можем перейти к теме поста.
Решение
Собственно, с точки зрения возможных решений, существует несколько подходов, которые имеют различную поддержку среди готовых библиотек (сервисов):
Загрузка целиком GeoJSON и рендер его (большинство отваливаются на этом варианте :)). Собственно преимущество, в том что практически все популярные библиотеки Google Карты, Yandex Карты, Mapbox, Leaflet и т.д., его так или иначе поддерживают. Однако, далеко не все делают это эффективно, например, по запросу в гугл по поводу эффективного решения для загрузки большого числа точек в Mapbox первой ссылкой будет их решение — supercluster, который по факту является серверной утилитой, которая загружает, подготавливает GeoJSON данные и возвращает их клиенту.
Загрузка только находящегося в viewport. Идея довольно простая, мы загружаем только то что находится в viewport (* в некоторых случаях лениво подгружаются и близлежащие тайлы). Реализация такого есть в коробке например в Yandex Картах — LoadingObjectManager, в том числе он может делать и кластеризацию на клиенте. У них есть и RemoteObjectManager, который уже ожидает кластеризованные данные от сервера.
Предгенерация статичных тайлов и загрузка их. Тоже имеет место быть, особенно в случае с высоконагруженными сервисами, но не особо интересно. Чаще всего генерируются тайлы с помощью инструмента, как например Mapnik и заливаются на CDN, либо используется сторонняя утилита/библиотека, которая делает всю эту работу самостоятельно.
- Mapbox Vector Tiles, собственно один из векторных форматов для карт, который описывает различные геометрии, их стилистику и т.д… Идея при использовании такого метода заключается в формировании своего MVT эндпоинта, который собственно может:
- Возвращать геометрии
- Кластеризовать точки
- Упрощать геометрии на малых уровнях зума
- Другое
Данный формат отлично поддерживается решениями от Mapbox, так же есть библиотеки для Leaflet.
С точки зрения хранилища для ГИС данных, которое бы к тому же давало возможность эффективно проводить операции над ними можно выбрать PostGIS, который к слову даёт все необходимые операции для описанного выше, в том числе и генерацию MVT (Mapbox Vector Tiles):
- Включение геометрии в тайл (прямоугольник) с помощью оператора
@
- Генерация MVT — ST_AsMVT, ST_AsMVTGeom
Спасибо за внимание, надеюсь на конструктивный фидбэк, если будет интересно могу рассказать ещё о некоторых моментах работы с картами!
Комментарии (3)
za90
01.04.2018 11:21Выглядит как небольшая заметка для себя. Обзор кратенько и самопиар небольшой. Извините, но это минус.
PS: продолжение хоть будет?
Melorian
Так какой способ-то? :D
GetJump Автор
Зависит от потребностей, но в целом это 2 или 4 — ый. Я сам сейчас в разрабатываемом проекте остановился на втором, поскольку там уже были Яндекс Карты, в целом я сторонник векторного решения, как более состоятельного, но нужно потратить немного больше сил на бэкэнд, в идеале вообще была бы около микросервисная архитектура и использование готового решение на JS (да, на нём действительно очень много всего).
Вообще, для своей книги я готовлю это всё очень подробно и даю некоторые хинты по поводу организации процессов, если будет лишнее время упрощу, обрежу и выложу на хабр и/или в свой блог.