Coloring objects | MapGL | 2GIS Documentation
MapGL JS API

Coloring objects

You can highlight various objects on the map by clicking them: buildings, roads, icons, etc. You can set different display settings for the default and selected states of an object. For example, a building in the default state can be gray, and in the selected state (when you click the building) it can be colored red.

You can configure the colors of an object in different states in two ways:

  • Using the Style editor. You can set common color settings for a group of objects. The display of objects is configured in the corresponding layer in the Style editor. For example, using separate layers, you can set color settings for administrative buildings, highways, etc. See the list of configured layers. When you click objects, they are colored according to the layer settings.
  • Using global map style variables. You can change the colors of any objects when you click them, regardless of the layer they belong to.

Using global style variables, you can also color objects not only when you click them, but also automatically when particular conditions are met (for example, color buildings with a particular number of floors).

In this example, when you click objects, they are colored according to the color settings for the selected state, which are specified in the style layers in the Style editor. To configure different objects, the corresponding style layers are used. For example, the colors of administrative buildings and residential buildings are specified in different layers. All objects belonging to one layer are colored the same.

In configured layers, the colors of objects in different states are already set, and you can change them in the Style editor if necessary. In this example, new color settings are set only for the layer with industrial buildings, while the other layers use the configured settings from the basic style.

For some layers, color settings in different states are not available, e.g. for water reservoirs (Water layer).

Usage example:

<!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: [55.16684876480724, 25.102715601296794],
                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>

To configure coloring objects on click using the Style editor:

  1. Set the style layer settings in the Style editor:

    1. Open the Style editor.

    2. Open the required style.

    3. Open the required layer. Specify color settings for the default and selected states.

      Example for industrial buildings (Industrial buildings layer):

      Object states
  2. To set up highlighting objects, add a click listener for the map and pass the IDs of the highlighted objects to the setSelectedObjects() method:

    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);
    });
    

    For more information on highlighting objects, see the Highlighting objects instruction.

In this example, when you click objects, they are colored according to the color settings that are passed in the global map style variables.

You can select three colors for coloring buildings using color palettes: the color of the walls, roof, and outline (the edges of the building). When you click buildings on the map, they are automatically colored in the selected colors. Administrative buildings, residential buildings, and other types of buildings have the same settings regardless of the layer they belong to.

Usage example:

<!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 of the building that are colored by default
    let selectedIds = ["70030076174035052"];

    const map = new mapgl.Map('container', {
        center: [55.2, 25.08552],
        zoom: 17,
        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>

To configure coloring objects on click using global style variables:

  1. Create a layer with 3D buildings:

    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']],
    };
    

    Initialize the following global map style variables:

    • wallColorTop - to set the roof color.
    • wallColorDown - to set the walls color.
    • strokeColor - to set the building outline color.
    • hoverId - to set the color only for highlighted buildings on the map.
  2. Pass the created global variables to the map.patchStyleState() method. Specify the initial colors for wallColorDown, wallColorTop and strokeColor, and pass the highlighted objects (the selectedIds array) to 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,
        });
    
        // Highlighting objects
        map.setSelectedObjects(selectedIds);
    
        // Adding a layer with buildings
        map.addLayer(building);
    });
    
  3. To configure highlighting of buildings on click, add a click listener for the map and pass the IDs of the highlighted objects to the map.patchStyleState() method:

    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. Create a function to update the colors of buildings that change depending on the colors selected in the palettes. Pass the new color values ​​to the map.patchStyleState() method:

    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');
    

You can color objects not only on click, but also according to certain conditions using global map style variables. For example, you can automatically color all buildings higher than five floors in the map viewport.

In this example, buildings are colored depending on the number of floors. First, buildings with the largest number of floors in the map viewport are highlighted and colored. Then buildings with a lower number of floors are colored, and so on. After all buildings in the map viewport are colored, the highlighting is automatically disabled, starting with the buildings with the fewest number of floors. You can select three colors for coloring buildings using color palettes: the color of the walls, roof, and outline (the edges of the building).

Usage example:

<!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 of the building that are colored by default
    let selectedIds = ["70030076174035052"];

    const map = new mapgl.Map('container', {
        center: [55.2, 25.08552],
        zoom: 17,
        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>

To configure coloring objects by conditions using global style variables:

  1. Create a layer with 3D buildings:

    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']]],
    };
    

    Initialize the following global map style variables:

    • wallColorTop - to set the roof color.
    • wallColorDown - to set the walls color.
    • strokeColor - to set the building outline color.
    • floorsCurrentHeight - to set the color of buildings with a certain number of floors.
  2. Pass the created global variables to the map.patchStyleState() method. Specify the initial colors for wallColorDown, wallColorTop and strokeColor, and pass the highlighted objects (the selectedIds array) to 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,
        });
    
        // Highlighting objects
        map.setSelectedObjects(selectedIds);
    
        // Adding a layer with buildings
        map.addLayer(building);
    });
    
  3. To configure highlighting of buildings on click, add a click listener for the map and pass the IDs of the highlighted objects to the map.patchStyleState() method:

    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. Create a function to update the colors of buildings that change depending on the colors selected in the palettes. Pass the new color values ​​to the map.patchStyleState() method:

    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. Set conditions for coloring buildings depending on the number of floors and pass the number of floors to the map.patchStyleState() method:

    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);