This page describes the heatmap utility that's available in the utility library for the Maps SDK for iOS. Heatmaps are useful for representing the distribution and density of data points on a map.

This video discusses the use of heatmaps as an alternative to markers, when your data requires a large number of data points on the map.

Heatmaps make it easy for viewers to understand the distribution and relative intensity of data points on a map. Rather than placing a marker at each location, heatmaps use color to represent the distribution of the data.

In the example below, red represents areas of high concentration of police stations in Victoria, Australia.

A map with a heatmap showing location of police stations
A heatmap on a map


Add a simple heatmap

To add a heatmap to your map, you will need a dataset consisting of the coordinates for each location of interest. First, create a GMUHeatmapTileLayer instance, setting the map property to a GMSMapView. Do this in your app's viewDidLoad() function, to ensure that the base map is loaded before working with the heatmap. Then pass a collection of GMUWeightedLatLng objects to the GMUHeatmapTileLayer instance.

The utility supplies the GMUHeatmapTileLayer class, which accepts a collection of GMUWeightedLatLng objects. It creates the tile images for various zoom levels, based on the radius, gradient and opacity options supplied.

Looking at the steps in more detail:

  1. Create a GMUHeatmapTileLayer instance, setting the map property to a GMSMapView (do this in your app's viewDidLoad() function).
  2. Pass a collection of GMUWeightedLatLng objects to the GMUHeatmapTileLayer instance.
  3. Call GMUHeatmapTileLayer.map, passing the map view.

    private var heatmapLayer: GMUHeatmapTileLayer!
    override func viewDidLoad() {
      heatmapLayer = GMUHeatmapTileLayer()
      heatmapLayer.map = mapView
    func addHeatmap()  {
      var list = [GMUWeightedLatLng]()
      do {
        // Get the data: latitude/longitude positions of police stations.
        if let path = Bundle.main.url(forResource: "police_stations", withExtension: "json") {
          let data = try Data(contentsOf: path)
          if let object = json as? [[String: Any]] {
            for item in object {
              let lat = item["lat"]
              let lng = item["lng"]
              let coords = GMUWeightedLatLng(coordinate: CLLocationCoordinate2DMake(lat as! CLLocationDegrees, lng as! CLLocationDegrees), intensity: 1.0)
          } else {
            print("Could not read the JSON.")
      } catch {
      // Add the latlngs to the heatmap layer.
      heatmapLayer.weightedData = list

For this example, the data is stored in a JSON file, police_stations.json. Here is an extract from the file:

{"lat" : -37.1886, "lng" : 145.708 } ,
{"lat" : -37.8361, "lng" : 144.845 } ,
{"lat" : -38.4034, "lng" : 144.192 } ,
{"lat" : -38.7597, "lng" : 143.67 } ,
{"lat" : -36.9672, "lng" : 141.083 }

Customize the heatmap

The heatmap has several customizable properties. You can set the options when initially creating the GMUHeatmapTileLayer instance, or at any time by setting a new value for the option.

The following options are available:

  1. Radius: The size of the Gaussian blur applied to the heatmap, expressed in pixels. The default is 20. Must be between 10 and 50. Use GMUHeatmapTileLayer.radius to set the radius.

  2. Gradient: A range of colors that the heatmap uses to generate its color map, ranging from lowest to highest intensity. A GMUGradient is created using an integer array containing the colors, and a float array indicating the starting point for each color, given as a percentage of the maximum intensity, and expressed as a fraction from 0 to 1. You need to specify only one color for a single-colored gradient, or a minimum of two colors for a multi-colored gradient. The color map is generated using interpolation between those colors. The default gradient has two colors. The colorMapSize parameter defines the number of steps in the gradient. Larger numbers will result in a smoother gradient, while smaller numbers will give sharper transitions similar to a contour graph. Use GMUHeatmapTileLayer.gradient to set the gradient.

  3. Opacity: This is the opacity of the entire heatmap layer, and ranges from 0 to 1. The default is 0.7. Use GMUHeatmapTileLayer.opacity to set the opacity value.

For example, create a Gradient:

// Define the gradient colors and their start points.
private var gradientColors = [UIColor.green, UIColor.red]
private var gradientStartPoints = [0.2, 1.0] as? [NSNumber]
override func viewDidLoad() {
  heatmapLayer = GMUHeatmapTileLayer()
  // Create the gradient.
  heatmapLayer.gradient = GMUGradient(colors: gradientColors,
                                      startPoints: gradientStartPoints!,
                                      colorMapSize: 256)
  heatmapLayer.map = mapView

To change the opacity of an existing heatmap:

heatmapLayer.opacity = 0.7

Update an existing option

To update an option that has already been set, take these steps:

  1. Update the option to the desired value.
  2. Call GMUHeatmapTileLayer.clearTileCache().

Change the dataset

To change the dataset upon which a heatmap is built:

  1. Update your data collection. Use GMUHeatmapTileLayer.weightedData, passing an array of GMUWeightedLatLng.
  2. Call GMUHeatmapTileLayer.clearTileCache().

Remove a heatmap

To remove a heatmap, call GMUHeatmapTileLayer.map, passing nil.

heatmapLayer.map = nil

See the demo app

For another example of a heatmap implementation, take a look at the HeatmapViewController in the demo app that ships with the utility library. The setup guide shows you how to run the demo app.