Offline maps

Офлайн-карты в веб-картографии опираются на принцип локального хранения всех необходимых данных для рендеринга карты: векторных тайлов, растровых тайлов, стилей, шрифтов (glyphs) и спрайтов. Основная сложность заключается не в отображении, а в подготовке и синхронизации данных, которые обычно загружаются динамически с серверов Mapbox.

Ключевая идея офлайн-режима — замена сетевых запросов локальным источником данных, при этом рендеринг остаётся полностью идентичным онлайн-режиму благодаря WebGL-движку Mapbox GL JS.


Ограничения веб-картографии в офлайн-среде

Обычная архитектура Mapbox GL JS предполагает постоянные HTTP-запросы:

  • vector tiles (.pbf)
  • style JSON
  • sprite atlas (.png + .json)
  • glyph ranges (.pbf или .ttf)
  • metadata источников

В офлайн-среде эти зависимости становятся критичными:

  • отсутствие сети делает невозможной загрузку тайлов
  • кеш браузера недостаточен для больших регионов
  • CORS и token-based access перестают работать без предварительной подготовки
  • обновление данных требует синхронизации

Структура данных офлайн-карты

Офлайн-карта в контексте Mapbox GL JS обычно состоит из следующих слоёв хранения:

Векторные тайлы

Основной источник геометрии и атрибутов.

  • формат: Mapbox Vector Tile (MVT)
  • хранение: MBTiles или отдельные файлы .pbf
  • содержат: дороги, здания, POI, границы

В офлайн-режиме векторные тайлы часто переносятся в:

  • IndexedDB
  • SQLite (в гибридных приложениях)
  • локальные файловые хранилища (Electron / mobile wrappers)

Стиль карты

Style JSON описывает:

  • слои (layers)
  • источники (sources)
  • источники данных (tile URLs)
  • фильтры, paint и layout свойства

Для офлайн-режима необходимо:

  • заменить tile URL templates на локальные резолверы
  • убрать зависимость от CDN
  • зафиксировать версии стилей

Спрайты

Спрайты содержат иконки и UI-элементы карты.

Файлы:

  • sprite.png
  • sprite.json

Особенности офлайн-режима:

  • требуется локальная упаковка всех иконок
  • важно сохранять согласованность идентификаторов
  • возможна генерация sprite atlas на этапе сборки

Шрифты (glyphs)

Glyphs критичны для подписей карты.

  • формат: PBF-глифы по диапазонам Unicode
  • проблема офлайна: невозможность догрузки недостающих диапазонов

Решения:

  • предзагрузка всех необходимых диапазонов
  • ограничение языков
  • генерация локальных font stacks

Подходы к реализации офлайн-режима

1. Pre-caching через Service Worker

Service Worker перехватывает сетевые запросы и возвращает локальные данные.

Основные шаги:

  • регистрация Service Worker
  • кэширование тайлов при первом запуске
  • перехват запросов Mapbox GL JS

Ключевой механизм — Cache Storage API:

  • хранение tile JSON
  • хранение PBF файлов
  • хранение sprite/glyph ресурсов

2. Локальный tile server

Вместо CDN используется локальный сервер:

  • Node.js + tilelive
  • Flask / FastAPI backend
  • embedded server в Electron

Mapbox GL JS продолжает работать как в онлайн-режиме, но URL источников указывает на localhost.

Преимущество:

  • минимальные изменения в коде

Недостаток:

  • требуется запуск сервера

3. Offline-first через IndexedDB

Данные загружаются заранее и сохраняются в IndexedDB.

Структура хранения:

  • ключ: z/x/y
  • значение: бинарный PBF

При запросе Mapbox GL JS:

  • кастомный transformRequest
  • перехват URL тайлов
  • возврат Blob из IndexedDB

Интеграция через transformRequest

Mapbox GL JS позволяет перехватывать все запросы через transformRequest.

Этот механизм является основой большинства офлайн-реализаций.

Логика:

  • анализ URL запроса
  • определение типа ресурса (tile, sprite, glyph)
  • подмена на локальный источник

Типичный сценарий:

  • mapbox://... → локальный ключ
  • https://api.mapbox.com/... → IndexedDB / Cache Storage
  • fallback → network (если доступен)

Кэширование векторных тайлов

Векторные тайлы — наиболее тяжёлый компонент офлайн-карт.

Стратегии хранения:

Полное предзагружение региона

Используется для:

  • навигационных приложений
  • туристических офлайн-карт

Минусы:

  • большой объём (сотни MB / GB)

Динамическое кэширование

Кэшируются только посещённые области.

Преимущества:

  • экономия памяти
  • постепенное накопление данных

Недостатки:

  • неполные данные при первом использовании

Гео-зональное разбиение

Данные делятся на:

  • bounding box
  • административные регионы
  • тайловые квадраты

Работа со стилями в офлайн-режиме

Style JSON требует модификации перед использованием офлайн.

Изменения:

  • удаление внешних URL
  • замена источников:
"tiles": ["offline://tiles/{z}/{x}/{y}"]
  • локализация sprite:
"sprite": "offline://sprite"
  • локальные glyphs:
"glyphs": "offline://glyphs/{fontstack}/{range}"

Обработка glyph ranges

Glyphs являются наиболее частой причиной ошибок офлайн-рендеринга.

Проблемы:

  • отсутствующие символы
  • неправильные диапазоны Unicode
  • разрыв текстовых слоёв

Решение:

  • генерация полного набора glyph ranges
  • использование ограниченного набора языков
  • предрендеринг популярных символов

Оптимизация хранения данных

Сжатие тайлов

Используются:

  • gzip
  • brotli
  • zstd (в нативных окружениях)

Дедупликация

Многие тайлы повторяются между зумами.

Методы:

  • hash-based deduplication
  • shared tile cache

LRU-кэш

Для ограниченной памяти:

  • удаление старых тайлов
  • приоритет текущего региона

Производительность офлайн-рендеринга

Mapbox GL JS использует WebGL pipeline:

  • vertex buffer для геометрии
  • fragment shaders для отрисовки слоёв
  • tile re-projection на GPU

В офлайн-режиме основная нагрузка смещается:

  • с сети на диск/память
  • с загрузки на декодирование PBF

Узкие места:

  • декодирование vector tiles
  • парсинг style JSON
  • загрузка glyph atlas

Гибридные офлайн-онлайн модели

Часто используется комбинированная модель:

  • офлайн: базовая карта региона
  • онлайн: актуальные данные и обновления

Стратегия:

  • offline-first fallback
  • синхронизация при появлении сети
  • версионирование тайлов

Безопасность и контроль версий

Офлайн-карты требуют строгого контроля:

  • версия стиля должна совпадать с тайлами
  • обновление данных должно быть атомарным
  • недопустимо смешивание разных датасетов

Рекомендуется:

  • semantic versioning для offline bundles
  • checksum для тайлов
  • manifest-файл описания пакета

Проблемы масштабирования

При росте офлайн-данных возникают ограничения:

  • размер storage quota браузера
  • скорость IndexedDB
  • время первой загрузки

Типовые решения:

  • сегментация регионов
  • progressive download
  • выборочное кэширование слоёв

Типовые архитектуры офлайн-систем

Веб-приложение (PWA)

  • Service Worker
  • Cache Storage
  • IndexedDB
  • Mapbox GL JS runtime

Electron-приложение

  • локальная файловая система
  • встроенный tile server
  • полный контроль ресурсов

Mobile wrapper (Capacitor / React Native WebView)

  • локальные asset bundles
  • preloaded tiles
  • native storage APIs

Ключевые принципы стабильной офлайн-картографии

  • все ресурсы должны быть предсказуемыми и версионированными
  • тайлы должны быть доступны без сети
  • glyphs и sprite не должны зависеть от CDN
  • style JSON должен быть автономным
  • кеширование должно контролироваться на уровне приложения

Поведение рендера при отсутствии сети

Mapbox GL JS продолжает работу даже при полном отсутствии сети, если:

  • все источники определены локально
  • transformRequest возвращает данные из кэша
  • отсутствуют внешние ссылки в style

В противном случае возникают:

  • пустые слои
  • отсутствующие подписи
  • неотображаемые иконки
  • частично рендеренные тайлы