Зауважте: коли масив точок перевищує 10 000, стандартні бібліотеки починають гальмувати: FPS падає до 15, користувач помічає лаги при скролі. Особливо критично це для додатків доставки, де відображення щільності замовлень у реальному часі — ключова метрика. Якщо карта підвисає при кожному завантаженні даних, водії не бачать актуальну картину, а аналітики втрачають час на завантаження звітів. Наша команда мобільних розробників з досвідом понад 5 років на ринку реалізувала 40+ проєктів, заощадивши клієнтам до $5000 щомісяця на серверних витратах. Ми реалізували 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 секунди. Навіть на флагманських пристроях це призводить до скидання кадрів і негативного досвіду користувача. Порівняно з Canvas-рішеннями, Google Maps Heatmap працює в 10 разів швидше. Рішення — агрегація на сервері.
| Розмір датасету | 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 тижнів після здачі.
Оцінимо проєкт безкоштовно — зв'яжіться з нами, розкажіть про ваш датасет, і ми запропонуємо оптимальне рішення. Отримайте консультацію щодо вашого проєкту.
Термін: два-три дні — інтеграція бібліотеки, серверна агрегація (якщо потрібна), налаштування динамічного зума, кольорова схема.







