> For the complete documentation index, see [llms.txt](https://docs.mapbox.com/ios/ja/maps/llms.txt)

# Visualize data as a heatmap

![Display your heatmap using the globe projection.](https://docs.mapbox.com/ios/ja/assets/ideal-img/maps-examples-heatmap.5a7ecf8.480.png)

This example demonstrates the creation of a heatmap layer and a circle layer using the **Mapbox Maps SDK for iOS**.

After loading source data using [`geoJSONSource`](https://docs.mapbox.com/ios/maps/api/latest/documentation/mapboxmaps/geojsonsource/), the `createHeatmapLayer()` function sets up layer configuration including using [`expressions`](https://docs.mapbox.com/style-spec/reference/expressions/) to vary colors and intensities based on density and magnitude. It also adjusts the color, weight, intensity, and radius of the heatmap dynamically with zoom level. It then adds the layer to the map. The `createCircleLayer()` function indicates earthquake magnitudes using colored circles whose sizes change with magnitude. The opacity and stroke properties of the circle layer also adjust based on the zoom level.

The visibility of the 2 layers transitions based on zoom level (between zoom levels `7` and `9`) using opacity, visualizing the data as a heat map when zoomed out and as circles on higher zooms.

> **Note: iOS Examples App Available**
> 
> This example code is part of the **Maps SDK for iOS Examples App**, a working iOS project [available on Github](https://github.com/mapbox/mapbox-maps-ios/tree/11.29.0/Sources/Examples). iOS developers are encouraged to run the examples app locally to interact with this example in an emulator and explore other features of the Maps SDK.
> 
> See our [Run the Maps SDK for iOS Examples App](https://docs.mapbox.com/help/tutorials/maps-sdk-ios-examples-app/) tutorial for step-by-step instructions.

**Swift**

Title: `HeatmapLayerGlobeExample.swift`

[View on GitHub](https://github.com/mapbox/mapbox-maps-ios/blob/main/Sources/Examples/All%20Examples/HeatmapLayerGlobeExample.swift)

```swift
import UIKit
import MapboxMaps

final class ViewController: UIViewController {
    private var mapView: MapView!
    private var cancelables = Set<AnyCancelable>()

    override func viewDidLoad() {
        super.viewDidLoad()

        // Center the map over the United States.
        let centerCoordinate = CLLocationCoordinate2D(latitude: 50, longitude: -120)
        let options = MapInitOptions(cameraOptions: CameraOptions(center: centerCoordinate, zoom: 1.0))

        // Set up map view
        mapView = MapView(frame: view.bounds, mapInitOptions: options)
        mapView.mapboxMap.mapStyle = .standard(theme: .monochrome, lightPreset: .night)
        mapView.ornaments.options.scaleBar.visibility = .hidden
        mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        try! self.mapView.mapboxMap.setProjection(StyleProjection(name: .globe))
        view.addSubview(mapView)

        mapView.mapboxMap.onMapLoaded.observeNext { [weak self] _ in
            guard let self = self else { return }
            try! self.mapView.mapboxMap.setAtmosphere(Atmosphere())
            self.addRuntimeLayers()
            
        }.store(in: &cancelables)
    }

    func addRuntimeLayers() {
        createEarthquakeSource()
        createCircleLayer()
        createHeatmapLayer()
    }

    func createEarthquakeSource() {
        var earthquakeSource = GeoJSONSource(id: self.earthquakeSourceId)
        earthquakeSource.data = .url(self.earthquakeURL)
        earthquakeSource.generateId = true

        do {
            try mapView.mapboxMap.addSource(earthquakeSource)
        } catch {
            print("Ran into an error adding a source: \(error)")
        }
    }

    func createHeatmapLayer() {

        // Add earthquake-viz layer
        var heatmapLayer = HeatmapLayer(id: self.heatmapLayerId, source: self.earthquakeSourceId)
        heatmapLayer.maxZoom = 9.0
        heatmapLayer.sourceLayer  = self.heatmapLayerSource

        heatmapLayer.heatmapColor = .expression(
            Exp(.interpolate) {
                Exp(.linear)
                Exp(.heatmapDensity)
                0
                "rgba(33.0, 102.0, 172.0, 0.0)"
                0.2
                "rgb(102.0, 169.0, 207.0)"
                0.4
                "rgb(209.0, 229.0, 240.0)"
                0.6
                "rgb(253.0, 219.0, 199.0)"
                0.8
                "rgb(239.0, 138.0, 98.0)"
                1
                "rgb(178.0, 24.0, 43.0)"
            }
        )
        // Increase the heatmap weight based on frequency and property magnitude
        heatmapLayer.heatmapWeight = .expression(
            Exp(.interpolate) {
                Exp(.linear)
                Exp(.get) {"mag"}
                0
                0
                6
                1
            }
        )
        // Increase the heatmap color weight weight by zoom level
        // heatmap-intensity is a multiplier on top of heatmap-weight
        heatmapLayer.heatmapIntensity = .expression(
            Exp(.interpolate) {
                Exp(.linear)
                Exp(.zoom)
                0
                1
                9
                3
            }
        )
        // Adjust the heatmap radius by zoom level
        heatmapLayer.heatmapRadius = .expression(
            Exp(.interpolate) {
                Exp(.linear)
                Exp(.zoom)
                0
                2
                9
                20
            }
        )

        // Transition from heatmap to circle layer by zoom level
        heatmapLayer.heatmapOpacity = .expression(
            Exp(.interpolate) {
                Exp(.linear)
                Exp(.zoom)
                7
                1
                9
                0
            }
        )

        do {
            try mapView.mapboxMap.addLayer(heatmapLayer)
        } catch {
            print("Ran into an error adding a layer: \(error)")
        }
    }

    func createCircleLayer() {

        // Add circle layer
        var circleLayer = CircleLayer(id: self.circleLayerId, source: self.earthquakeSourceId)

        // Adjust the circle layer radius by zoom level
        circleLayer.circleRadius = .expression(
            Exp(.interpolate) {
                Exp(.linear)
                Exp(.zoom)
                7
                Exp(.interpolate) {
                    Exp(.linear)
                    Exp(.get) { "mag" }
                    1
                    1
                    6
                    4
                }
                16
                Exp(.interpolate) {
                    Exp(.linear)
                    Exp(.get) { "mag" }
                    1
                    5
                    6
                    50
                }
            }
        )

        circleLayer.circleRadiusTransition = StyleTransition(duration: 0.5, delay: 0)
        circleLayer.circleStrokeColor = .constant(StyleColor(.black))
        circleLayer.circleStrokeWidth = .constant(1)

        // Set circle layer color by mag level
        circleLayer.circleColor = .expression(
            Exp(.interpolate) {
                Exp(.linear)
                Exp(.get) { "mag" }
                1
                "rgba(33.0, 102.0, 172.0, 0.0)"
                2
                "rgb(102.0, 169.0, 207.0)"
                3
                "rgb(209.0, 229.0, 240.0)"
                4
                "rgb(253.0, 219.0, 199.0)"
                5
                "rgb(239.0, 138.0, 98.0)"
                6
                "rgb(178.0, 24.0, 43.0)"
            }
        )

        // Adjust the circle laye opacity by zoom level
        circleLayer.circleOpacity = .expression(
            Exp(.interpolate) {
                Exp(.linear)
                Exp(.zoom)
                7
                0
                8
                1
            }
        )

        circleLayer.circleStrokeColor = .constant(.init(UIColor.white))
        circleLayer.circleStrokeWidth = .constant(0.1)

        // `LightPreset`s are applied to all layers of the map.
        // As `.night` is applied we need to set `circleEmissiveStrength` to color the circles
        circleLayer.circleEmissiveStrength = .constant(1)

        do {
            try mapView.mapboxMap.addLayer(circleLayer)
        } catch {
            print("Ran into an error adding a layer: \(error)")
        }
    }

}

private extension ViewController {
    var earthquakeSourceId: String { "earthquakes" }
    var earthquakeLayerId: String { "earthquake-viz" }
    var heatmapLayerId: String { "earthquakes-heat" }
    var heatmapLayerSource: String { "earthquakes" }
    var circleLayerId: String { "earthquakes-circle" }
    var earthquakeURL: URL { URL(string: "https://www.mapbox.com/mapbox-gl-js/assets/earthquakes.geojson")! }
}
```