Офлайн-режим

Офлайн-режим в картографических приложениях на базе HERE Technologies реализуется как комбинация локального хранения геоданных, предварительно загруженных тайлов, автономных маршрутизаторов и ограниченного поискового индекса. В контексте HERE Maps API for JavaScript офлайн-функциональность строится вокруг принципа предзагрузки и последующего обращения к локальному источнику данных вместо сетевых сервисов.

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


Модель данных и офлайн-пакеты

Офлайн-режим невозможен без предварительной подготовки данных, которые загружаются на устройство. В экосистеме HERE данные группируются в так называемые офлайн-пакеты.

Пакеты включают:

  • базовые векторные или растровые тайлы карты;
  • дорожный граф для маршрутизации;
  • ограничения движения (повороты, односторонние дороги, скоростные лимиты);
  • упрощённые POI (Points of Interest);
  • индексы для локального поиска (в ограниченном объёме).

Обычно такие пакеты создаются на серверной стороне HERE Location Suite и затем доставляются в клиентское приложение. В JavaScript API доступ к ним осуществляется через слой сервисов платформы и офлайн-хранилище браузера.


Инициализация платформы и переключение режимов

В стандартной конфигурации HERE Maps API работает через облачные сервисы. Для офлайн-режима используется переключение источников данных на локальный провайдер.

Типовая логика включает:

  • определение доступности сети;
  • проверку наличия локальных пакетов;
  • переключение tile provider на offline source;
  • замещение сервисов маршрутизации и геокодинга локальными аналогами.

Пример концептуальной инициализации:

const platform = new H.service.Platform({
  apikey: 'YOUR_API_KEY'
});

const isOffline = !navigator.onLine;

const defaultLayers = platform.createDefaultLayers({
  tileSize: 512,
  ppi: 320
});

const map = new H.Map(
  document.getElementById('map'),
  isOffline ? defaultLayers.vector.offline : defaultLayers.vector.normal.map,
  {
    zoom: 12,
    center: { lat: 49.8, lng: 73.1 }
  }
);

В реальных приложениях переключение слоя карты дополняется переопределением сервисов H.service для маршрутов и поиска.


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

Основой офлайн-картографии являются тайлы. В HERE Maps API они могут быть векторными или растровыми, в зависимости от конфигурации проекта.

Основные стратегии хранения:

IndexedDB

  • хранение бинарных тайлов;
  • структурированные индексы по координатам (z/x/y);
  • высокая производительность при больших объёмах данных.

Cache Storage (Service Worker)

  • перехват HTTP-запросов к tile endpoints;
  • автоматическое кэширование ответов;
  • быстрый доступ при повторных загрузках.

LocalStorage

  • используется только для метаданных (не тайлы);
  • хранение состояния пакетов, версий и конфигурации.

Service Worker как основа офлайн-доставки

Service Worker играет центральную роль в архитектуре офлайн-карт. Он перехватывает запросы к tile-серверам и направляет их либо в кэш, либо в локальную базу данных.

Типовая логика:

  • перехват запросов /maptile/ или аналогичных endpoint;
  • проверка наличия ресурса в Cache Storage;
  • fallback в IndexedDB;
  • возврат локального ответа в формате image/png или vector tile protobuf.

Пример упрощённого обработчика:

self.addEventListener('fetch', event => {
  const url = new URL(event.request.url);

  if (url.pathname.includes('/maptile/')) {
    event.respondWith(
      caches.match(event.request).then(cached => {
        if (cached) return cached;

        return fetch(event.request).then(response => {
          const responseClone = response.clone();
          caches.open('here-map-tiles').then(cache => {
            cache.put(event.request, responseClone);
          });
          return response;
        });
      })
    );
  }
});

В продакшн-сценариях логика усложняется добавлением версионирования пакетов и контроля целостности данных.


Офлайн-маршрутизация

Маршрутизация в офлайн-режиме требует локального графа дорог. В HERE экосистеме он представляет собой сжатую структуру, содержащую узлы (junctions) и рёбра (edges) с весами.

В JavaScript API используется абстракция H.service.RoutingService, которая в офлайн-конфигурации заменяется локальным вычислительным модулем.

Ограничения офлайн-маршрутизации:

  • отсутствие актуальных пробок;
  • невозможность динамического пересчёта из-за дорожных событий;
  • ограниченная поддержка альтернативных маршрутов;
  • фиксированная актуальность данных на момент загрузки пакета.

Алгоритмически чаще всего применяется модифицированный Dijkstra или A* с эвристикой расстояния.


Геокодинг и обратный геокодинг

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

В стандартном режиме запросы адресов отправляются в облачные сервисы HERE Technologies, однако в офлайн-режиме используется локальный индекс:

  • сокращённый словарь адресов;
  • приоритет крупных объектов (улицы, города);
  • отсутствие полнотекстового поиска по всем POI;
  • использование префиксных деревьев (Trie) для ускорения поиска.

Пример поведения:

  • ввод “Al-Farabi” → локальный матч по улицам;
  • ввод “coffee” → может не дать результата без интернет-подключения.

Ограничения офлайн-режима

Офлайн-картография в HERE Maps API for JavaScript имеет ряд системных ограничений, обусловленных отсутствием доступа к облачным данным:

  • отсутствие актуализации дорожной ситуации;
  • невозможность загрузки новых POI в реальном времени;
  • ограниченный поиск по категориям;
  • невозможность работы с динамическими слоями (погода, трафик, события);
  • ограничение размера офлайн-пакетов на устройство.

Эти ограничения компенсируются предзагрузкой данных и грамотной архитектурой кэширования.


Синхронизация онлайн и офлайн данных

Гибридный режим является наиболее распространённым сценарием. Приложение переключается между источниками данных в зависимости от состояния сети.

Типовая модель:

  • онлайн → запрос к HERE cloud services;
  • офлайн → локальный provider;
  • восстановление сети → синхронизация изменений;
  • обновление пакетов → фоновая загрузка.

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


Производительность и оптимизация

Офлайн-карты предъявляют высокие требования к оптимизации клиентской части приложения.

Основные техники:

Сжатие данных

  • использование протоколов protobuf для векторных тайлов;
  • gzip/brotli для передачи пакетов.

Ленивая загрузка

  • подгрузка тайлов только для текущего viewport;
  • предиктивная загрузка соседних областей.

Кэш-иерархия

  • L1: память браузера;
  • L2: Cache Storage;
  • L3: IndexedDB.

Управление памятью

  • удаление устаревших тайлов;
  • лимитирование размера пакетов;
  • TTL для кэшированных объектов.

Пример комплексной интеграции офлайн-карт

const platform = new H.service.Platform({ apikey: 'YOUR_KEY' });

const layers = platform.createDefaultLayers();

const map = new H.Map(
  document.getElementById('map'),
  layers.vector.normal.map,
  {
    zoom: 13,
    center: { lat: 52.52, lng: 13.405 }
  }
);

// Проверка состояния сети
function updateMode() {
  const offline = !navigator.onLine;

  if (offline) {
    map.setBaseLayer(layers.vector.offline);
  } else {
    map.setBaseLayer(layers.vector.normal.map);
  }
}

window.addEventListener('online', updateMode);
window.addEventListener('offline', updateMode);

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


Безопасность и целостность данных

Офлайн-данные требуют проверки целостности перед использованием:

  • контрольные суммы пакетов;
  • цифровая подпись данных;
  • проверка версии API и совместимости форматов;
  • защита от повреждённых тайлов.

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