Skip to content

Create a Heatmap layer on globe

html
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Create a Heatmap layer on a globe</title>
    <meta
      property="og:description"
      content="Create a Heatmap layer on a globe."
    />
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link
      rel="stylesheet"
      cssLink.href = "https://cdn.mapmetrics-atlas.net/versions/latest/mapmetrics-gl.css";
    />
    <script src="https://cdn.mapmetrics-atlas.net/versions/latest/mapmetrics-gl.js"></script>
    <style>
      body {
        margin: 0;
        padding: 0;
      }

      html,
      body,
      #map {
        height: 100%;
      }
    </style>
  </head>

  <body>
    <div id="map"></div>
    <script>
      const accessToken = "<YOUR_ACCESS_TOKEN>";

      const map = new mapmetricsgl.Map({
        container: "map",
        style: `${accessToken}`,
        maxPitch: 55,
        center: [-120, 37.422],
        zoom: 2,
        bearing: 10,
        hash: true,
      });

      map.on('style.load', () => {
        map.setStyle(map.getStyle(), {
        transformStyle: (previousStyle, nextStyle) => {
          nextStyle.projection = { type: "globe" };
          nextStyle.sources = {
            ...nextStyle.sources,
          };

          nextStyle.sky = {
            "atmosphere-blend": [
              "interpolate",
              ["linear"],
              ["zoom"],
              0,
              1,
              2,
              0,
            ],
          };

          return nextStyle;
        },
      });
      });

      map.addControl(
        new mapmetricsgl.NavigationControl({
          visualizePitch: true,
          showZoom: true,
          showCompass: true,
        })
      );

      map.addControl(new mapmetricsgl.GlobeControl());

      map.on("load", () => {
        // Add a geojson point source.
        // Heatmap layers also work with a vector tile source.
        map.addSource("earthquakes", {
          type: "geojson",
          data: "https://cdn.mapmetrics-atlas.net/Images/heatmap.geojson",
        });

        map.addLayer({
          id: "earthquakes-heat",
          type: "heatmap",
          source: "earthquakes",
          maxzoom: 9,
          paint: {
            // Increase the heatmap weight based on frequency and property magnitude
            "heatmap-weight": [
              "interpolate",
              ["linear"],
              ["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
            "heatmap-intensity": [
              "interpolate",
              ["linear"],
              ["zoom"],
              0,
              1,
              9,
              3,
            ],
            // Color ramp for heatmap.  Domain is 0 (low) to 1 (high).
            // Begin color ramp at 0-stop with a 0-transparency color
            // to create a blur-like effect.
            "heatmap-color": [
              "interpolate",
              ["linear"],
              ["heatmap-density"],
              0,
              "rgba(33,102,172,0)",
              0.2,
              "rgb(103,169,207)",
              0.4,
              "rgb(209,229,240)",
              0.6,
              "rgb(253,219,199)",
              0.8,
              "rgb(239,138,98)",
              1,
              "rgb(178,24,43)",
            ],
            // Adjust the heatmap radius by zoom level
            "heatmap-radius": [
              "interpolate",
              ["linear"],
              ["zoom"],
              0,
              2,
              9,
              20,
            ],
            // Transition from heatmap to circle layer by zoom level
            "heatmap-opacity": [
              "interpolate",
              ["linear"],
              ["zoom"],
              7,
              1,
              9,
              0,
            ],
          },
        });

        map.addLayer({
          id: "earthquakes-point",
          type: "circle",
          source: "earthquakes",
          minzoom: 7,
          paint: {
            // Size circle radius by earthquake magnitude and zoom level
            "circle-radius": [
              "interpolate",
              ["linear"],
              ["zoom"],
              7,
              ["interpolate", ["linear"], ["get", "mag"], 1, 1, 6, 4],
              16,
              ["interpolate", ["linear"], ["get", "mag"], 1, 5, 6, 50],
            ],
            "circle-color": [
              "interpolate",
              ["linear"],
              ["get", "mag"],
              1,
              "rgba(33,102,172,0)",
              2,
              "rgb(103,169,207)",
              3,
              "rgb(209,229,240)",
              4,
              "rgb(253,219,199)",
              5,
              "rgb(239,138,98)",
              6,
              "rgb(178,24,43)",
            ],
            "circle-stroke-color": "white",
            "circle-stroke-width": 1,
            // Transition from heatmap to circle layer by zoom level
            "circle-opacity": ["interpolate", ["linear"], ["zoom"], 7, 0, 8, 1],
          },
        });
      });
    </script>
  </body>
</html>
jsx
import React, { useEffect, useRef } from 'react';
import mapmetricsgl from '@mapmetrics/mapmetrics-gl';
import '@mapmetrics/mapmetrics-gl/dist/mapmetrics-gl.css';

const CreateHeatmapGlobe = () => {
  const mapContainerRef = useRef(null);
  const mapRef = useRef(null);

  useEffect(() => {
    if (!mapContainerRef.current || mapRef.current) return;

    const accessToken = "<YOUR_ACCESS_TOKEN>";

    const map = new mapmetricsgl.Map({
      container: mapContainerRef.current,
      style: `${accessToken}`,
      maxPitch: 55,
      center: [-120, 37.422],
      zoom: 2,
      bearing: 10,
      hash: true,
    });

    map.addControl(
      new mapmetricsgl.NavigationControl({
        visualizePitch: true,
        showZoom: true,
        showCompass: true,
      })
    );

    map.addControl(new mapmetricsgl.GlobeControl());

    map.on("load", () => {
      // Set globe projection and sky
      map.setProjection({ type: "globe" });

      const currentStyle = map.getStyle();
      currentStyle.sky = {
        "atmosphere-blend": [
          "interpolate",
          ["linear"],
          ["zoom"],
          0,
          1,
          2,
          0,
        ],
      };
      map.setStyle(currentStyle);


      // Add a geojson point source
      map.addSource("earthquakes", {
        type: "geojson",
        data: "https://cdn.mapmetrics-atlas.net/Images/heatmap.geojson",
      });

      map.addLayer({
        id: "earthquakes-heat",
        type: "heatmap",
        source: "earthquakes",
        maxzoom: 9,
        paint: {
          "heatmap-weight": [
            "interpolate",
            ["linear"],
            ["get", "mag"],
            0,
            0,
            6,
            1,
          ],
          "heatmap-intensity": [
            "interpolate",
            ["linear"],
            ["zoom"],
            0,
            1,
            9,
            3,
          ],
          "heatmap-color": [
            "interpolate",
            ["linear"],
            ["heatmap-density"],
            0,
            "rgba(33,102,172,0)",
            0.2,
            "rgb(103,169,207)",
            0.4,
            "rgb(209,229,240)",
            0.6,
            "rgb(253,219,199)",
            0.8,
            "rgb(239,138,98)",
            1,
            "rgb(178,24,43)",
          ],
          "heatmap-radius": [
            "interpolate",
            ["linear"],
            ["zoom"],
            0,
            2,
            9,
            20,
          ],
          "heatmap-opacity": [
            "interpolate",
            ["linear"],
            ["zoom"],
            7,
            1,
            9,
            0,
          ],
        },
      });

      map.addLayer({
        id: "earthquakes-point",
        type: "circle",
        source: "earthquakes",
        minzoom: 7,
        paint: {
          "circle-radius": [
            "interpolate",
            ["linear"],
            ["zoom"],
            7,
            ["interpolate", ["linear"], ["get", "mag"], 1, 1, 6, 4],
            16,
            ["interpolate", ["linear"], ["get", "mag"], 1, 5, 6, 50],
          ],
          "circle-color": [
            "interpolate",
            ["linear"],
            ["get", "mag"],
            1,
            "rgba(33,102,172,0)",
            2,
            "rgb(103,169,207)",
            3,
            "rgb(209,229,240)",
            4,
            "rgb(253,219,199)",
            5,
            "rgb(239,138,98)",
            6,
            "rgb(178,24,43)",
          ],
          "circle-stroke-color": "white",
          "circle-stroke-width": 1,
          "circle-opacity": ["interpolate", ["linear"], ["zoom"], 7, 0, 8, 1],
        },
      });
    });

    mapRef.current = map;

    return () => {
      map.remove();
      mapRef.current = null;
    };
  }, []);

  return (
    <div
      ref={mapContainerRef}
      style={{
        height: '100%',
        width: '100%'
      }}
    />
  );
};

export default CreateHeatmapGlobe;