Отметим: когда массив точек превышает 10 000, стандартные библиотеки начинают тормозить: FPS падает до 15, пользователь замечает лаги при скролле. Особенно критично это для приложений доставки, где отображение плотности заказов в реальном времени — ключевая метрика. Если карта подвисает при каждой загрузке данных, водители не видят актуальную картину, а аналитики теряют время на загрузку отчётов. Наша команда мобильных разработчиков с опытом более 5 лет сталкивается с этими задачами постоянно. Мы реализовали 40+ проектов с тепловыми картами — от стартапов до крупных логистических платформ, где датасеты достигают 500 000 точек в день.
Рассмотрим конкретный пример: в проекте доставки еды мы интегрировали тепловую карту с 200 000 точек. Без агрегации приложение зависало на 4 секунды при каждом зуме. После внедрения серверной агрегации по сетке FPS поднялся до 55, а время загрузки сократилось до 200 мс. Это позволило диспетчерам видеть плотность заказов в реальном времени без задержек.
По данным Google Maps iOS Utils, тайловый рендеринг эффективен для датасетов до 10 000 точек.
Как рендерятся тепловые карты
Каждая библиотека строит heatmap через kernel density estimation: для каждой точки на экране считается взвешенная сумма вкладов от всех точек данных в заданном радиусе. Результат — bitmap-слой поверх карты.
iOS: GMUHeatmapTileLayer из google-maps-ios-utils. Данные — массив GMUWeightedLatLng. Радиус градиента, минимальная интенсивность и цветовая схема настраиваются через свойства слоя. Тайловый механизм означает, что при скролле карты новые тайлы рендерятся на лету — без лага, если датасет не огромный.
Android: HeatmapTileProvider из android-maps-utils. Принцип аналогичный. Передаём Collection<LatLng> или Collection<WeightedLatLng> для взвешенных точек.
Flutter: google_maps_flutter не включает heatmap из коробки. Два варианта: нативный platform channel к GMSMapView/MapView с GMUHeatmapTileLayer / HeatmapTileProvider, или библиотека flutter_map + flutter_map_heatmap на основе canvas.
Почему стандартные библиотеки не справляются с большими данными?
Главная проблема: передавать 50 000 точек в GMUHeatmapTileLayer и ждать, пока он их обработает на main thread — получить ANR или заморозку на 3-4 секунды. Даже на флагманских устройствах это приводит к сбросу кадров и негативному пользовательскому опыту. Решение — агрегация на сервере.
| Размер датасета | FPS без агрегации | FPS с агрегацией |
|---|---|---|
| 5 000 | 55 | 60 |
| 10 000 | 30 | 58 |
| 50 000 | 10 | 55 |
| 100 000 | 5 | 50 |
Как агрегировать данные на сервере без потери точности?
Вместо 50 000 сырых точек сервер возвращает уже агрегированные данные по сетке (grid aggregation): каждая ячейка сетки — одна точка с весом, равным количеству событий в ячейке. При зуме 10 — сетка 500×500 метров, при зуме 14 — 50×50 метров. Количество точек сокращается до 200-500 вне зависимости от исходного объёма.
Серверная агрегация через PostGIS:
SELECT round(lat::numeric, 3) AS lat_grid, round(lon::numeric, 3) AS lon_grid, COUNT(*) AS weight FROM events WHERE created_at > now() - interval '7 days' GROUP BY lat_grid, lon_grid; При изменении зума карты — перезапрашиваем агрегацию с новой точностью округления. Дебаунс 500 мс на событие изменения зума обязателен. Подробнее о GMUHeatmapTileLayer.
| Платформа | Библиотека | Агрегация | Производительность |
|---|---|---|---|
| iOS | GMUHeatmapTileLayer | Нативная + серверная | Хорошая до 10 000 точек, с агрегацией — до 100 000+ |
| Android | HeatmapTileProvider | Нативная + серверная | Аналогично iOS |
| Flutter | Platform channel / flutter_map | Только серверная | Зависит от реализации, рекомендуется агрегация |
Как обеспечить быструю загрузку агрегированных данных?
Агрегация на сервере — только половина решения. Без кэширования клиент будет перезапрашивать данные при каждом изменении зума, что создаёт избыточную нагрузку. Мы используем двухуровневое кэширование: на сервере — материализованные представления PostGIS с обновлением по крону, на клиенте — LRU-кэш на последние 10 уровней зума. Время ответа API сокращается с 300 до 20 мс.
Также важна предварительная загрузка: как только пользователь касается карты, мы фоново загружаем соседние тайлы для следующего уровня зума. Это делает переходы между масштабами незаметными.
Цветовые схемы и интерпретация
Стандартная цветовая схема (синий → зелёный → жёлтый → красный) интуитивна, но не подходит для людей с дальтонизмом. Для B2B-аналитики лучше работает одноцветный градиент (белый → тёмно-синий) или кастомная схема бренда.
GMUHeatmapTileLayer принимает [GMUGradient] с массивом цветов и позиций — настраивается без пересборки. Мы гарантируем, что цветовая схема будет адаптирована под ваши корпоративные стандарты.
Настройка для людей с дальтонизмом
Используйте одноцветный градиент (например, от белого к тёмно-синему) или шкалу с текстурой. Для точной настройки проводим тестирование с эмуляцией дальтонизма.Как интегрировать тепловую карту за 5 шагов
- Выбор библиотеки — определяем платформу (iOS/Android/Flutter) и выбираем подходящую библиотеку.
- Настройка слоя — конфигурируем радиус, градиент, интенсивность.
- Серверная агрегация — реализуем эндпоинт с агрегацией по сетке (если датасет >10 000).
- Динамический зум — добавляем обработчик изменения зума с дебаунсом.
- Тестирование — проверяем производительность на реальных устройствах.
Что входит в работу
- Интеграция библиотеки heatmap с настройкой под ваш стек.
- Серверная агрегация данных с использованием PostgreSQL/PostGIS.
- Оптимизация производительности (FPS, расход памяти).
- Документация по эксплуатации и исходный код.
- Поддержка в течение 2 недель после сдачи.
Оценим проект бесплатно — свяжитесь с нами, расскажите о вашем датасете, и мы предложим оптимальное решение. Получите консультацию по вашему проекту.
Срок: два-три дня — интеграция библиотеки, серверная агрегация (если нужна), настройка динамического зума, цветовая схема.







