Тепловая карта | MapGL | 2GIS Documentation
MapGL JS API

Тепловая карта

С помощью источника данных GeoJSON и стилей карты на карте можно нарисовать тепловой слой: набор градиентных кругов, которые сливаются в единый объект при приближении к друг другу.

Чтобы это сделать, нужно подключить источник данных с помощью метода GeoJsonSource(), указав уникальный аттрибут для этого источника (например, purpose: 'heatmap'). Подключаемый GeoJSON должен состоять только из объектов Point и MultiPoint (центры кругов).

⚠ Тепловая карта не поддерживается в режиме отображения 3D-рельефа на карте.

const data = {
    type: 'FeatureCollection',
    features: [
        {
            type: 'Feature',
            properties: { customProperty: 1 },
            geometry: {
                type: 'MultiPoint',
                coordinates: [
                    [55.44, 25.34],
                    [55.43, 25.37],
                    [55.41, 25.34],
                ],
            },
        },
        {
            type: 'Feature',
            properties: { customProperty: 2 },
            geometry: {
                type: 'Point',
                coordinates: [55.4, 25.3],
            },
        },
    ],
};

const source = new mapgl.GeoJsonSource(map, {
    data,
    attributes: {
        purpose: 'heatmap',
    },
});

После этого нужно создать стиль для теплового слоя, указав для него тип heatmap и фильтр по указанному при подключении GeoJSON аттрибуту (purpose = heatmap).

const layer = {
    id: 'my-heatmap-layer',
    filter: ['match', ['sourceAttr', 'purpose'], ['heatmap'], true, false],
    type: 'heatmap',
    style: {
        color: [
            'interpolate',
            ['linear'],
            ['heatmap-density'],
            0,
            'rgba(0, 0, 0, 0)',
            0.2,
            'rgba(172, 32, 135, 1)',
            0.4,
            'rgba(255, 154, 0, 1)',
            0.6,
            'rgba(255, 252, 0, 1)',
            0.8,
            'rgba(255, 255, 63, 1)',
            1,
            'rgba(255, 255, 255, 1)',
        ],
        radius: 50,
        weight: ['get', 'customProperty'],
        intensity: 0.8,
        opacity: 0.8,
        downscale: 1,
    },
};

map.on('styleload', () => {
    map.addLayer(layer);
});

Описание параметров:

  • color - набор цветов для градиента, от периметра (0.0) до центра круга (1.0). Для периметра важно указать прозрачный цвет, иначе им будет закрашена вся карта.
  • radius - радиус круга в пикселях.
  • weight - интенсивность точки. Чем выше значение, тем больше размер центра круга (сильнее будут преобладать цвета ближе к 1.0 из массива color). В качестве значения имеет смысл указывать только ExtractorExpression или InterpolateExpression, используя одно из свойств объекта, иначе интенсивность будет применена ко всем точкам.
  • intensity - модификатор интенсивности для всех точек теплового слоя.
  • opacity - прозрачность слоя (1 - слой непрозрачный, 0 - слой полностью прозрачный).
  • downscale - модификатор разрешения. Чем выше значение, тем ниже качество изображения теплового слоя и выше скорость отрисовки. По умолчанию 1.
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>2GIS Map API</title>
        <meta name="description" content="Heatmap layer example" />
        <style>
            html,
            body,
            #container {
                margin: 0;
                width: 100%;
                height: 100%;
                overflow: hidden;
            }
        </style>
    </head>
    <body>
        <div id="container"></div>
        <script src="https://mapgl.2gis.com/api/js/v1"></script>
        <script>
            const map = new mapgl.Map('container', {
                center: [55.425, 25.355],
                zoom: 10,
                key: 'Your API access key',
            });

            const data = {
                type: 'FeatureCollection',
                features: [
                    {
                        type: 'Feature',
                        properties: { customProperty: 1 },
                        geometry: {
                            type: 'MultiPoint',
                            coordinates: [
                                [55.44, 25.34],
                                [55.43, 25.37],
                                [55.41, 25.34],
                            ],
                        },
                    },
                    {
                        type: 'Feature',
                        properties: { customProperty: 2 },
                        geometry: {
                            type: 'Point',
                            coordinates: [55.4, 25.3],
                        },
                    },
                ],
            };

            const source = new mapgl.GeoJsonSource(map, {
                data,
                attributes: {
                    purpose: 'heatmap',
                },
            });

            const layer = {
                id: 'my-heatmap-layer', // Each layer ID must be unique

                // Data filtering logic
                filter: [
                    'match',
                    ['sourceAttr', 'purpose'],
                    ['heatmap'],
                    true, // Result if value of purpose source attribute equals "heatmap"
                    false, // Result if not
                ],

                // Drawing object type
                type: 'heatmap',

                // Style of drawing object
                style: {
                    color: [
                        'interpolate',
                        ['linear'],
                        ['heatmap-density'],
                        0,
                        'rgba(0, 0, 0, 0)',
                        0.2,
                        'rgba(172, 32, 135, 1)',
                        0.4,
                        'rgba(255, 154, 0, 1)',
                        0.6,
                        'rgba(255, 252, 0, 1)',
                        0.8,
                        'rgba(255, 255, 63, 1)',
                        1,
                        'rgba(255, 255, 255, 1)',
                    ],
                    radius: 50,
                    weight: ['get', 'customProperty'],
                    intensity: 0.8,
                    opacity: 0.8,
                    downscale: 1,
                },
            };

            map.on('styleload', () => {
                map.addLayer(layer);
            });
        </script>
    </body>
</html>