Раскрашивание объектов | MapGL | 2GIS Documentation
MapGL JS API

Раскрашивание объектов

Вы можете выделять на карте с помощью клика различные объекты: здания, дороги, иконки и т. д. Для обычного и выделенного состояния объекта вы можете задавать разные настройки отображения. Например, здание в обычном состоянии может иметь серый цвет, а в выделенном (при клике на здание) перекрашиваться в красный цвет.

Вы можете настроить цвета объекта в разных состояниях двумя способами:

  • С помощью Редактора стилей. Вы можете задавать общие настройки цвета для группы объектов, отображение которых настраивается в соответствующем слое в Редакторе стилей. Например, с помощью отдельных слоёв можно задать настройки цветов административных зданий, магистральных дорог и так далее: см. список готовых слоёв. При клике на объекты они будут раскрашиваться согласно настройкам слоя.
  • С помощью глобальных переменных стиля карты. Вы можете изменять цвета любых объектов при клике на них независимо от слоя, которому они принадлежат.

С помощью глобальных стилевых переменных вы также можете раскрашивать объекты не при клике, а автоматически при выполнении определённых условий (например, раскрашивать здания с определённым количеством этажей).

В этом примере при клике на объекты они будут раскрашиваться согласно настройкам цвета для выделенного состояния, которые указаны в стилевых слоях в Редакторе стилей. Для настроек разных объектов используются соответствующие стилевые слои, например, цвета административных зданий и жилых зданий задаются в разных слоях. Все объекты, принадлежащие одному слою, раскрашиваются одинаково.

В готовых слоях цвета объектов в разных состояниях настроены заранее, и при необходимости вы можете изменить их в Редакторе стилей. В этом примере новые настройки цвета задаются только для слоя с промышленными зданиями, а для остальных слоёв используются готовые настройки из базового стиля.

Для некоторых слоёв настройка цвета в разных состояниях недоступна, например, для водоёмов (слой Water).

Пример использования:

<!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="An object selection 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: [37.629589, 55.746067],
                zoom: 17,
                key: 'Your API access key'
            });

            let selectedIds = [];

            map.on('click', (e) => {
                if (!e.target) {
                    return;
                }

                const { id } = e.target;

                if (selectedIds.includes(id)) {
                    selectedIds = selectedIds.filter((i) => i !== id);
                } else {
                    selectedIds.push(id);
                }

                map.setSelectedObjects(selectedIds);
            });
        </script>
    </body>
</html>

Чтобы настроить раскрашивание объектов при клике с помощью Редактора стилей:

  1. Задайте настройки стилевого слоя в Редакторе стилей:

    1. Откройте Редактор стилей.

    2. Откройте нужный стиль.

    3. Откройте нужный слой. Укажите настройки цвета для обычного и выделенного состояния.

      Пример для промышленных зданий (слой Industrial buildings):

      Состояния объекта
  2. Чтобы настроить выделение объектов, добавьте обработчик кликов для карты и передайте ID выделенных объектов в метод setSelectedObjects():

    let selectedIds = [];
    
    map.on('click', (e) => {
        if (!e.target) {
            return;
        }
    
        const { id } = e.target;
    
        if (selectedIds.includes(id)) {
            selectedIds = selectedIds.filter((i) => i !== id);
        } else {
            selectedIds.push(id);
        }
    
        map.setSelectedObjects(selectedIds);
    });
    

    Подробнее о выделении объектов см. в инструкции Выделение объектов.

В этом примере при клике на объекты они будут раскрашиваться согласно настройкам цвета, которые передаются в глобальных переменных стиля карты.

Вы можете выбирать три цвета для раскраски зданий с помощью цветовых палитр: цвет стен, крыши и обводки (рёбер здания). При клике на здания на карте они будут автоматически раскрашиваться в выбранные цвета. Административные здания, жилые здания и другие типы зданий будут иметь одинаковые настройки независимо от слоя, которому они принадлежат.

Пример использования:

<!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>

    <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>
<div id="colors" style="position: absolute; top: 0; left: 0; display: flex; gap:15px; flex-direction: column; height: 100%; padding-top: 15px; padding-left: 15px;">
    <rgba-color-picker id='wallDown' style="width: 150px; height: 150px;" color='{
  "r": 143,
  "g": 219,
  "b": 126,
  "a": 1
}'></rgba-color-picker>
    <rgba-color-picker id='wallTop' style="width: 150px; height: 150px;" color='{
  "r": 237,
  "g": 255,
  "b": 155,
  "a": 1
}'></rgba-color-picker>
    <rgba-color-picker id='strokeColor' style="width: 150px; height: 150px;" color='{
  "r": 205,
  "g": 250,
  "b": 152,
  "a": 0.9
}'></rgba-color-picker>
</div>
<script src="https://mapgl.2gis.com/api/js/v1"></script>
<script type="module">
    import 'https://esm.sh/vanilla-colorful/rgba-color-picker';
    const colorPicker = document.querySelector('rgba-color-picker');
    colorPicker.color = { r: 143, g: 219, b: 126, a: 1 };
</script>
<script>
    const building = {
        id: "wallsSelectLayer",
        type: "polygonExtrusion",
        style: {
            topColor: [
                "match",
                ["to-boolean", ["global", "wallColorTop"]],
                [true],
                ["to-color", ["global", "wallColorTop"]],
                "rgba(1,1,1,1)"],
            sideColor:
                [
                    "match",
                    ["to-boolean", ["global", "wallColorDown"]],
                    [true],
                    ["to-color", ["global", "wallColorDown"]],
                    "rgba(1,1,1,1)"],
            visibility: "visible",
            strokeColor:
                [
                    "match",
                    ["to-boolean", ["global", "strokeColor"]],
                    [true],
                    ["to-color", ["global", "strokeColor"]],
                    "rgba(1,1,1,1)"],
            strokeWidth: 0.1
        },
        filter: [
            "in",
            ["get", "db_id"], ["global","hoverId"],
        ]
    };

    // ID здания, которое будет раскрашено по умолчанию
    let selectedIds = ["4504235283020869"];

    const map = new mapgl.Map('container', {
        center: [37.629589, 55.746067],
        zoom: 17.2,
        rotation: -40,
        pitch: 45,
        key: 'Your API access key',
    });

    window.map = map;

    map.on("styleload", () => {
        map.patchStyleState({
            wallColorDown: "rgba(143,219,126,1)",
            wallColorTop: "rgba(237,255,155,1)",
            strokeColor: "rgba(237,255,155,1)",
            hoverId: selectedIds,
        });
        map.setSelectedObjects(selectedIds);
        map.addLayer(building);
    });

    map.on("click", (ev) => {
        const id = ev.target?.id;
        if (!id) return;
        selectedIds = selectedIds.includes(id)
            ? selectedIds.filter((selectId) => selectId !== id)
            : [...selectedIds, id];
        map.patchStyleState({ hoverId: selectedIds });
    });

    function updateColor(pickerId, stateKey) {
        const picker = document.getElementById(pickerId);
        picker?.addEventListener("color-changed", (event) => {
            const v = event.detail?.value;
            if (!v) return;
            map.patchStyleState({
                [stateKey]: `rgba(${v.r},${v.g},${v.b},${v.a})`
            });
        });
    }
    updateColor("wallDown", "wallColorDown");
    updateColor("wallTop", "wallColorTop");
    updateColor("strokeColor", "strokeColor");
</script>
</body>
</html>

Чтобы настроить раскрашивание объектов при клике с помощью глобальных стилевых переменных:

  1. Создайте слой с 3D-зданиями:

    const building = {
        id: 'wallsSelectLayer',
        type: 'polygonExtrusion',
        style: {
            topColor: [
                'match',
                ['to-boolean', ['global', 'wallColorTop']],
                [true],
                ['to-color', ['global', 'wallColorTop']],
                'rgba(1,1,1,1)',
            ],
            sideColor: [
                'match',
                ['to-boolean', ['global', 'wallColorDown']],
                [true],
                ['to-color', ['global', 'wallColorDown']],
                'rgba(1,1,1,1)',
            ],
            visibility: 'visible',
            strokeColor: [
                'match',
                ['to-boolean', ['global', 'strokeColor']],
                [true],
                ['to-color', ['global', 'strokeColor']],
                'rgba(1,1,1,1)',
            ],
            strokeWidth: 0.1,
        },
        filter: ['in', ['get', 'db_id'], ['global', 'hoverId']],
    };
    

    Инициализируйте следующие глобальные переменные стиля карты:

    • wallColorTop — для настройки цвета крыши;
    • wallColorDown — для настройки цвета стен;
    • strokeColor — для настройки цвета обводки зданий;
    • hoverId — для настройки цвета только для выделенных зданий на карте.
  2. Передайте в метод map.patchStyleState() созданные глобальные переменные. Укажите начальные цвета для wallColorDown, wallColorTop и strokeColor, а также передайте выделенные объекты (массив selectedIds) в hoverId:

    window.map = map;
    
    map.on('styleload', () => {
        map.patchStyleState({
            wallColorDown: 'rgba(143,219,126,1)',
            wallColorTop: 'rgba(237,255,155,1)',
            strokeColor: 'rgba(237,255,155,1)',
            hoverId: selectedIds,
        });
    
        // Выделение объектов
        map.setSelectedObjects(selectedIds);
    
        // Добавление слоя со зданиями
        map.addLayer(building);
    });
    
  3. Чтобы настроить выделение зданий по клику, добавьте обработчик кликов для карты и передайте ID выделенных объектов в метод map.patchStyleState():

    map.on('click', (ev) => {
        const id = ev.target?.id;
        if (!id) return;
        selectedIds = selectedIds.includes(id)
            ? selectedIds.filter((selectId) => selectId !== id)
            : [...selectedIds, id];
        map.patchStyleState({ hoverId: selectedIds });
    });
    
  4. Создайте функцию для обновления цветов зданий, которые будут меняться в зависимости от выбранных цветов в палитрах, и передайте новые значения цвета в метод map.patchStyleState():

    function updateColor(pickerId, stateKey) {
        const picker = document.getElementById(pickerId);
        picker?.addEventListener('color-changed', (event) => {
            const v = event.detail?.value;
            if (!v) return;
            map.patchStyleState({
                [stateKey]: `rgba(${v.r},${v.g},${v.b},${v.a})`,
            });
        });
    }
    updateColor('wallDown', 'wallColorDown');
    updateColor('wallTop', 'wallColorTop');
    updateColor('strokeColor', 'strokeColor');
    

Вы можете раскрашивать объекты не только при клике, а по определённым условиям с помощью глобальных переменных стиля карты. Например, автоматически раскрашивать все здания выше пяти этажей в области видимости карты.

В этом примере здания раскрашиваются в зависимости от количества этажей: сначала выделяются и раскрашиваются здания с наибольшим количеством этажей в области видимости карты, затем раскрашиваются здания с количеством этажей меньше на один и так далее. После того как все здания в области видимости карты раскрашены, автоматически снимается выделение, начиная со зданий с наименьшим количеством этажей. Вы можете выбирать три цвета для раскраски зданий с помощью цветовых палитр: цвет стен, крыши и обводки (рёбер здания).

Пример использования:

<!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>

    <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>
<div id="colors" style="position: absolute; top: 0; left: 0; display: flex; gap:15px; flex-direction: column; height: 100%; padding-top: 15px; padding-left: 15px;">
    <rgba-color-picker id='wallDown' style="width: 150px; height: 150px;" color='{
  "r": 143,
  "g": 219,
  "b": 126,
  "a": 1
}'></rgba-color-picker>
    <rgba-color-picker id='wallTop' style="width: 150px; height: 150px;" color='{
  "r": 237,
  "g": 255,
  "b": 155,
  "a": 1
}'></rgba-color-picker>
    <rgba-color-picker id='strokeColor' style="width: 150px; height: 150px;" color='{
  "r": 205,
  "g": 250,
  "b": 152,
  "a": 0.9
}'></rgba-color-picker>
</div>
<script src="https://mapgl.2gis.com/api/js/v1"></script>
<script type="module">
    import 'https://esm.sh/vanilla-colorful/rgba-color-picker';
</script>
<script>
    const building = {
        id: "wallsSelectLayer",
        type: "polygonExtrusion",
        style: {
            topColor: [
                "match",
                ["to-boolean", ["global", "wallColorTop"]],
                [true],
                ["to-color", ["global", "wallColorTop"]],
                "rgba(1,1,1,1)"],
            sideColor:
                [
                    "match",
                    ["to-boolean", ["global", "wallColorDown"]],
                    [true],
                    ["to-color", ["global", "wallColorDown"]],
                    "rgba(1,1,1,1)"],
            visibility: "visible",
            strokeColor:
                [
                    "match",
                    ["to-boolean", ["global", "strokeColor"]],
                    [true],
                    ["to-color", ["global", "strokeColor"]],
                    "rgba(1,1,1,1)"],
            strokeWidth: 0.1
        },
        filter: ["all", [">", ["get", "db_height"], ["global", "floorsCurrentHeight"]]]
    };

    // ID здания, которое будет раскрашено по умолчанию
    let selectedIds = ["70030076552334291"];

    const map = new mapgl.Map('container', {
        center: [37.629589, 55.746067],
        zoom: 17.2,
        rotation: -40,
        pitch: 45,
        key: 'Your API access key',
    });

    window.map = map;

    map.on("styleload", () => {
        map.patchStyleState({
            wallColorDown: "rgba(143,219,126,1)",
            wallColorTop: "rgba(237,255,155,1)",
            strokeColor: "rgba(237,255,155,1)",
            hoverId: selectedIds,
        });
        map.setSelectedObjects(selectedIds);
        map.addLayer(building);
    });

    map.on("click", async (ev) => {

        const id = ev.target && ev.target.id;
        if (selectedIds.includes(id)) {
            selectedIds = selectedIds.filter((selectId) => selectId !== id);
        } else {
            selectedIds.push(id);
        }
        map.patchStyleState({
            hoverId: selectedIds,
        });
        map.setSelectedObjects(selectedIds);
    });

    function updateColor(pickerId, stateKey) {
        const picker = document.getElementById(pickerId);
        picker?.addEventListener("color-changed", (event) => {
            const v = event.detail?.value;
            if (!v) return;
            map.patchStyleState({
                [stateKey]: `rgba(${v.r},${v.g},${v.b},${v.a})`
            });
        });
    }
    updateColor("wallDown", "wallColorDown");
    updateColor("wallTop", "wallColorTop");
    updateColor("strokeColor", "strokeColor");

    const MAX_FLOOR_HEIGHT = 8000;
    let STEP = 500;
    let currentFloorHeight = MAX_FLOOR_HEIGHT;
    let isDecreasing = false;

    setInterval(() => {
        if(isDecreasing){
            STEP = -500;
        }else{
            STEP = 500;
        }

        if(currentFloorHeight <= 0){
            isDecreasing = true;
        }else if(currentFloorHeight > MAX_FLOOR_HEIGHT){
            isDecreasing = false;
        }

        currentFloorHeight = currentFloorHeight - STEP;
        map.patchStyleState({ floorsCurrentHeight: currentFloorHeight });
    }, 1000);
</script>
</body>
</html>

Чтобы настроить раскрашивание объектов по условиям с помощью глобальных стилевых переменных:

  1. Создайте слой с 3D-зданиями:

    const building = {
        id: 'wallsSelectLayer',
        type: 'polygonExtrusion',
        style: {
            topColor: [
                'match',
                ['to-boolean', ['global', 'wallColorTop']],
                [true],
                ['to-color', ['global', 'wallColorTop']],
                'rgba(1,1,1,1)',
            ],
            sideColor: [
                'match',
                ['to-boolean', ['global', 'wallColorDown']],
                [true],
                ['to-color', ['global', 'wallColorDown']],
                'rgba(1,1,1,1)',
            ],
            visibility: 'visible',
            strokeColor: [
                'match',
                ['to-boolean', ['global', 'strokeColor']],
                [true],
                ['to-color', ['global', 'strokeColor']],
                'rgba(1,1,1,1)',
            ],
            strokeWidth: 0.1,
        },
        filter: ['all', ['>', ['get', 'db_height'], ['global', 'floorsCurrentHeight']]],
    };
    

    Инициализируйте следующие глобальные переменные стиля карты:

    • wallColorTop — для настройки цвета крыши;
    • wallColorDown — для настройки цвета стен;
    • strokeColor — для настройки цвета обводки зданий;
    • floorsCurrentHeight — для настройки цвета зданий с определённым количеством этажей.
  2. Передайте в метод map.patchStyleState() созданные глобальные переменные. Укажите начальные цвета для wallColorDown, wallColorTop и strokeColor, а также передайте выделенные объекты (массив selectedIds) в hoverId:

    window.map = map;
    
    map.on('styleload', () => {
        map.patchStyleState({
            wallColorDown: 'rgba(143,219,126,1)',
            wallColorTop: 'rgba(237,255,155,1)',
            strokeColor: 'rgba(237,255,155,1)',
            hoverId: selectedIds,
        });
    
        // Выделение объектов
        map.setSelectedObjects(selectedIds);
    
        // Добавление слоя со зданиями
        map.addLayer(building);
    });
    
  3. Чтобы настроить выделение зданий по клику, добавьте обработчик кликов для карты и передайте ID выделенных объектов в метод map.patchStyleState():

    map.on('click', async (ev) => {
        const id = ev.target && ev.target.id;
        if (selectedIds.includes(id)) {
            selectedIds = selectedIds.filter((selectId) => selectId !== id);
        } else {
            selectedIds.push(id);
        }
        map.patchStyleState({
            hoverId: selectedIds,
        });
        map.setSelectedObjects(selectedIds);
    });
    
  4. Создайте функцию для обновления цветов зданий, которые будут меняться в зависимости от выбранных цветов в палитрах, и передайте новые значения цвета в метод map.patchStyleState():

    function updateColor(pickerId, stateKey) {
        const picker = document.getElementById(pickerId);
        picker?.addEventListener('color-changed', (event) => {
            const v = event.detail?.value;
            if (!v) return;
            map.patchStyleState({
                [stateKey]: `rgba(${v.r},${v.g},${v.b},${v.a})`,
            });
        });
    }
    updateColor('wallDown', 'wallColorDown');
    updateColor('wallTop', 'wallColorTop');
    updateColor('strokeColor', 'strokeColor');
    
  5. Задайте условия для раскрашивания зданий в зависимости от количества этажей и передайте количество этажей в метод map.patchStyleState():

    const MAX_FLOOR_HEIGHT = 8000;
    let STEP = 500;
    let currentFloorHeight = MAX_FLOOR_HEIGHT;
    let isDecreasing = false;
    
    setInterval(() => {
        if (isDecreasing) {
            STEP = -500;
        } else {
            STEP = 500;
        }
    
        if (currentFloorHeight <= 0) {
            isDecreasing = true;
        } else if (currentFloorHeight > MAX_FLOOR_HEIGHT) {
            isDecreasing = false;
        }
    
        currentFloorHeight = currentFloorHeight - STEP;
        map.patchStyleState({ floorsCurrentHeight: currentFloorHeight });
    }, 1000);