Heatmap
The MapConductorHeatmap module provides a map-implementation-agnostic heatmap overlay. It renders heatmap data as a raster layer and works with any map provider.
Use heatmaps when each point has a numeric weight and the user needs to understand density or intensity over an area rather than inspect individual markers.
Installation
Section titled “Installation”Add to your Package.swift:
.package(url: "https://github.com/MapConductor/ios-heatmap", from: "1.1.0"),In your target dependencies:
.product(name: "MapConductorHeatmap", package: "ios-heatmap"),Basic Usage
Section titled “Basic Usage”Use HeatmapPointView for a small number of points or when the points are naturally declared as SwiftUI content inside the overlay:
import MapConductorHeatmap
GoogleMapView(state: mapViewState) { HeatmapOverlay( radiusPx: 20, opacity: 0.7 ) { HeatmapPointView( position: GeoPoint(latitude: 35.6762, longitude: 139.6503), weight: 1.0 ) HeatmapPointView( position: GeoPoint(latitude: 35.6895, longitude: 139.6917), weight: 2.5 ) }}Batch Points
Section titled “Batch Points”For large datasets, use HeatmapPoints to add all points in a single update. This avoids many separate point appear/disappear updates:
let pointStates: [HeatmapPointState] = [...]
GoogleMapView(state: mapViewState) { HeatmapOverlay(radiusPx: 20) { HeatmapPoints(pointStates) }}HeatmapPoint is the internal data value used by the renderer. In map content, use HeatmapPointView or HeatmapPoints.
Dynamic State
Section titled “Dynamic State”Use HeatmapOverlayState to control heatmap properties at runtime:
struct DynamicHeatmapMap: View { @StateObject private var heatmapState = HeatmapOverlayState( radiusPx: 20, opacity: 0.7 ) @StateObject private var mapViewState = GoogleMapViewState()
var body: some View { VStack { GoogleMapView(state: mapViewState) { HeatmapOverlay(state: heatmapState) { HeatmapPoints(pointStates) } }
HStack { Text("Radius:") Slider(value: .init( get: { Double(heatmapState.radiusPx) }, set: { heatmapState.radiusPx = Int($0) } ), in: 10...50)
Text("Opacity:") Slider(value: $heatmapState.opacity, in: 0...1) } .padding() } }}Custom Gradient
Section titled “Custom Gradient”let gradient = HeatmapGradient( stops: [ HeatmapGradientStop(position: 0.0, color: UIColor(red: 0, green: 0, blue: 1, alpha: 1)), // Blue HeatmapGradientStop(position: 0.5, color: UIColor(red: 0, green: 1, blue: 0, alpha: 1)), // Green HeatmapGradientStop(position: 1.0, color: UIColor(red: 1, green: 0, blue: 0, alpha: 1)) // Red ])
let heatmapState = HeatmapOverlayState(gradient: gradient)HeatmapOverlayState also supports maxIntensity, weightProvider, tileSize, trackPointUpdates, and disableTileServerCache through its initializers. Use those when you need consistent intensity scaling, custom weighting, or tile-cache behavior for frequently changing datasets.
Use Cases
Section titled “Use Cases”- Population Density: Visualize population distribution
- Crime Hotspots: Show crime incident concentration
- Traffic Intensity: Display traffic congestion
- Weather Patterns: Show temperature or precipitation
- Business Concentration: Visualize business density
- Network Usage: Show network traffic patterns
- Geographic Data: Visualize any location-based numerical data
Performance Considerations
Section titled “Performance Considerations”- Radius: Larger radius = better performance but less detail
- Point Count: Limit points to reasonable numbers for smooth rendering
- Opacity: Lower opacity reduces visual clutter
- Zoom Level: Adjust radius based on current zoom level
- Batch Updates: Prefer
HeatmapPointsfor large arrays
Best Practices
Section titled “Best Practices”- Progressive Loading: Load data in chunks for large datasets
- Zoom-Based Radius: Adjust radius as user zooms
- Color Scheme: Choose colors that are meaningful for your data
- Update Efficiently: Batch updates instead of individual point changes
- Test Performance: Verify smooth rendering with expected data volume
- User Feedback: Show loading state while processing large datasets