Shapes | MapGL | 2GIS Documentation
MapGL JS API

Shapes

You can draw custom shapes on the map, such as circles, polygons, and polylines.

To draw a circle on the map, create a Circle object and specify the center coordinates and radius in meters. You can additionally specify the color of the circle and stroke options. See CircleOptions for more details.

const circle = new mapgl.Circle(map, {
    coordinates: map.getCenter(),
    radius: 2000,
    color: '#ff000055',
    strokeWidth: 2,
    strokeColor: '#ffffff',
});
<!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="Circle geometry 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.31878, 25.23584],
                zoom: 13,
                key: 'Your API access key',
            });

            const circle = new mapgl.Circle(map, {
                coordinates: map.getCenter(),
                radius: 2000,
                color: '#ff000055',
                strokeWidth: 2,
                strokeColor: '#ffffff',
            });

            circle.on('click', () => {
                alert('Circle click');
            });
        </script>
    </body>
</html>

Alternatively, create a CircleMarker object if you want to specify the radius in pixels. This way, the size of the circle will be unaffected by zooming.

const circleMarker = new mapgl.CircleMarker(map, {
    coordinates: map.getCenter(),
    radius: 80,
    color: '#ff0000',
    strokeWidth: 2,
    strokeColor: '#ffffff',
});
<!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="CircleMarker geometry 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.31878, 25.23584],
                zoom: 13,
                key: 'Your API access key',
            });

            const circleMarker = new mapgl.CircleMarker(map, {
                coordinates: map.getCenter(),
                radius: 80,
                color: '#ff0000',
                strokeWidth: 2,
                strokeColor: '#ffffff',
            });

            circleMarker.on('click', () => {
                alert('circleMarker click');
            });
        </script>
    </body>
</html>

To draw a polygon on the map, create a Polygon object.

Polygon takes an array of arrays as the coordinates parameter. The first array is the coordinates of the polygon itself. All other arrays are optional and can be used to cut holes in the polygon (one extra array - one polygonal hole).

Make sure that the first and last coordinates in any of the arrays are the same. In other words, all polygons must be closed.

Additionally, you can specify the color of the polygon and stroke options. See PolygonOptions for more details.

const polygon = new mapgl.Polygon(map, {
    coordinates: [
        // Coordinates of the polygon
        [
            [55.28770929, 25.22069944],
            [55.28976922, 25.25656786],
            [55.33302789, 25.25687836],
            [55.33096795, 25.22007825],
            [55.28770929, 25.22069944],
        ],
        // Coordinates of the hole in the polygon
        [
            [55.29500489, 25.23979952],
            [55.31285768, 25.25175496],
            [55.32676225, 25.23917843],
            [55.31062608, 25.2279982],
            [55.29500489, 25.23979952],
        ],
    ],
    color: '#990000',
    strokeWidth: 3,
    strokeColor: '#bb0000',
});
<!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="Polygon geometry 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.31878, 25.23584],
                zoom: 13,
                key: 'Your API access key',
            });

            const polygon = new mapgl.Polygon(map, {
                coordinates: [
                    [
                        [55.28770929, 25.22069944],
                        [55.28976922, 25.25656786],
                        [55.33302789, 25.25687836],
                        [55.33096795, 25.22007825],
                        [55.28770929, 25.22069944],
                    ],
                    [
                        [55.29500489, 25.23979952],
                        [55.31285768, 25.25175496],
                        [55.32676225, 25.23917843],
                        [55.31062608, 25.2279982],
                        [55.29500489, 25.23979952],
                    ],
                ],
                color: '#99000055',
                strokeWidth: 3,
                strokeColor: '#bb0000',
            });

            polygon.on('click', () => {
                alert('Polygon click');
            });
        </script>
    </body>
</html>

To draw a polyline on the map, create a Polyline object and specify the line points coordinates, the width and the color of the line.

const polyline = new mapgl.Polyline(map, {
    coordinates: [
        [55.28770929, 25.22069944],
        [55.28976922, 25.25656786],
        [55.33096795, 25.22007825],
        [55.33302789, 25.25687836],
    ],
    width: 10,
    color: '#00b7ff',
});
<!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="Polyline geometry 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.31878, 25.23584],
                zoom: 13,
                key: 'Your API access key',
            });

            const polyline = new mapgl.Polyline(map, {
                coordinates: [
                    [55.28770929, 25.22069944],
                    [55.28976922, 25.25656786],
                    [55.33096795, 25.22007825],
                    [55.33302789, 25.25687836],
                ],
                width: 10,
                color: '#00b7ff',
            });

            polyline.on('click', () => {
                alert('Polyline click');
            });
        </script>
    </body>
</html>

Polyline does not have stroke options. Instead, you can draw multiple lines underneath each other to create a stroke/outline effect.

Specify the zIndex parameter so that the lines are correctly overlapped.

const polyline = new mapgl.Polyline(map, {
    coordinates: [
        [55.28770929, 25.22069944],
        [55.28976922, 25.25656786],
        [55.33096795, 25.22007825],
        [55.33302789, 25.25687836],
    ],
    width: 10,
    color: '#00b7ff',
    zIndex: 2,
});

const polylineStroke = new mapgl.Polyline(map, {
    coordinates: [
        [55.28770929, 25.22069944],
        [55.28976922, 25.25656786],
        [55.33096795, 25.22007825],
        [55.33302789, 25.25687836],
    ],
    width: 14,
    color: '#ffffff',
    zIndex: 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="Polyline geometry with extra draw stroke use extra polyline 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.31878, 25.23584],
            zoom: 13,
            key: 'Your API access key',
        });

        const polyline = new mapgl.Polyline(map, {
            coordinates: [
                [55.28770929, 25.22069944],
                [55.28976922, 25.25656786],
                [55.33096795, 25.22007825],
                [55.33302789, 25.25687836],
            ],
            width: 10,
            color: '#00b7ff',
            zIndex: 2
        });
        const polylineStroke = new mapgl.Polyline(map, {
            coordinates: [
                [55.28770929, 25.22069944],
                [55.28976922, 25.25656786],
                [55.33096795, 25.22007825],
                [55.33302789, 25.25687836],
            ],
            width: 14,
            color: '#ffffff',
            zIndex: 1
        });

        polyline.on('click', () => {
            alert('Polyline click');
        });
        polylineStroke.on('click', () => {
            alert('Polyline stroke click');
        });
    </script>
</body>

</html>

By default, Polyline creates a solid line.

To create a dashed line, you can specify the following parameters:

  • dashLength - length of the main line segments in pixels.
  • gapLength - length of the additional line segments (gaps) in pixels. If omitted, will be equal to dashLength.
  • gapColor - color of the additional line segments (gaps). If omitted, gaps will be fully transparent.
const polyline = new mapgl.Polyline(map, {
    coordinates: [
        [55.28770929, 25.22069944],
        [55.28976922, 25.25656786],
        [55.33096795, 25.22007825],
        [55.33302789, 25.25687836],
    ],
    width: 10,
    color: '#00b7ff',
    dashLength: 10,
    gapLength: 30,
    gapColor: '#ffffff39',
});
<!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="Polyline geometry example with apply dashed styles" />
        <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.31878, 25.23584],
                zoom: 13,
                key: 'Your API access key',
            });

            const polyline = new mapgl.Polyline(map, {
                coordinates: [
                    [55.28770929, 25.22069944],
                    [55.28976922, 25.25656786],
                    [55.33096795, 25.22007825],
                    [55.33302789, 25.25687836],
                ],
                width: 10,
                color: '#00b7ff',
                dashLength: 10,
                gapLength: 30,
                gapColor: '#ffffff39',
            });

            polyline.on('click', () => {
                alert('Polyline click');
            });
        </script>
    </body>
</html>

The renderingMode option specifies whether the line will be used in a depth buffer.

Compare the behavior of the polyline when switching the renderingMode value on the map below. In 3d mode, the line is hidden behind buildings and other objects.

const polyline3dOptions = {
    coordinates: [map.getBounds().southWest, map.getBounds().northEast],
    width: 5,
    renderingMode: '3d',
    dashLength: 5,
    gapColor: '#ff0000',
    color: '#00ff00',
};

In 2d mode, the line overlays all the objects.

const polyline2dOptions = {
    coordinates: [map.getBounds().southWest, map.getBounds().northEast],
    width: 5,
    renderingMode: '2d',
    dashLength: 5,
    gapColor: '#ff0000',
    color: '#00ff00',
};
<!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="Polyline rendering modes example" />
        <link rel="stylesheet" type="text/css" href="/css/switch.css" />
        <style>
            html,
            body,
            #container {
                margin: 0;
                width: 100%;
                height: 100%;
                overflow: hidden;
            }

            #buttons {
                position: absolute;
                z-index: 2;

                top: 0;
                left: 0;
                margin: 8px;
                padding: 2px 4px;

                display: flex;
                align-items: center;
                background-color: white;
                border-radius: 8px;
                font: 13px sans-serif;
            }

            #buttons label {
                padding: 0 4px;
            }
        </style>
    </head>
    <body>
        <div id="container"></div>
        <div id="buttons">
            <label>Rendering mode</label>
            <input type="checkbox" role="switch" onclick="toggleRenderingMode(event)" checked="true"/>
            <label id="stateCaption">3d</label>
        </div>
        <script src="https://mapgl.2gis.com/api/js/v1"></script>
        <script>
            const map = new mapgl.Map('container', {
                center: [55.31878, 25.23584],
                zoom: 19,
                key: 'Your API access key',
            });

            const polyline3dOptions = {
                coordinates: [map.getBounds().southWest, map.getBounds().northEast],
                width: 5,
                renderingMode: '3d',
                dashLength: 5,
                gapColor: '#ff0000',
                color: '#00ff00',
            };

            const polyline2dOptions = {
                coordinates: [map.getBounds().southWest, map.getBounds().northEast],
                width: 5,
                renderingMode: '2d',
                dashLength: 5,
                gapColor: '#ff0000',
                color: '#00ff00',
            };

            window.polyline = new mapgl.Polyline(map, polyline3dOptions);

            const stateCaption = document.getElementById('stateCaption');

            function toggleRenderingMode(ev) {
                const is3d = ev.target.checked;

                window.polyline.destroy();

                if (is3d) {
                    window.polyline = new mapgl.Polyline(map, polyline3dOptions);
                } else {
                    window.polyline = new mapgl.Polyline(map, polyline2dOptions);
                }

                stateCaption.innerText = is3d ? '3d' : '2d';
            }
        </script>
    </body>
</html>

Using the hiddenPartColor and the hiddenPartGapColor options, you can style parts of the line that are hidden behind buildings and other objects.

const polyline = new mapgl.Polyline(map, {
    coordinates: [map.getBounds().southWest, map.getBounds().northEast],
    width: 5,
    renderingMode: '3d',
    dashLength: 5,
    gapColor: '#ff0000',
    color: '#00ff00',
    hiddenPartColor: '#0000ff',
    hiddenPartGapColor: '#ffff00',
});
<!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="Polyline 3d rendering mode 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.31878, 25.23584],
                zoom: 19,
                key: 'Your API access key',
            });

            const polyline = new mapgl.Polyline(map, {
                coordinates: [map.getBounds().southWest, map.getBounds().northEast],
                width: 5,
                renderingMode: '3d',
                dashLength: 5,
                gapColor: '#ff0000',
                color: '#00ff00',
                hiddenPartColor: '#0000ff',
                hiddenPartGapColor: '#ffff00',
            });
        </script>
    </body>
</html>

You can add event listeners to any shape using the on() method. See DynamicObjectEventTable for the list of possible events.

For example, to add a click listener to a circle, you can use the following code:

circle.on('click', () => {
    alert('Circle click');
});

To destroy a shape, you should use the destroy() method. See the Circle reference.

For example, to destroy a circle, you can use the following code:

circle.destroy();

If you wish to destroy all shapes, you have to destroy each shape individually:

[circle, polygon].forEach((shape) => {
    shape.destroy();
});

You can use shapes to draw a car route between multiple points. To do this, connect multiple polylines to create a path.

First, create an array that will contain coordinates and other information for drawing route segments:

const segments = [
    {
        color: '#e84646',
        label: 'A',
        coords: [
            [55.29970489, 25.26853913],
            [55.2994345, 25.26920691],
            [55.29950714, 25.26936478],
        ],
    },
    {
        color: '#e3e340',
        coords: [
            [55.29950714, 25.26936478],
            [55.30124581, 25.26959538],
            [55.30141272, 25.26965618],
            [55.30191503, 25.26896923],
        ],
    },
    {
        color: '#43e843',
        label: 'B',
        coords: [
            [55.30191503, 25.26896923],
            [55.3020634, 25.26892939],
            [55.30233927, 25.26823968],
        ],
    },
];

Next, create a loop to draw the segments on the map. Do not forget to specify the zIndex parameter so that the lines are correctly overlapped.

Additionally, you can mark the beginning and end of the route using a combination of CircleMarker and Label.

segments.forEach((segment, i) => {
    const zIndex = segments.length - 1 - i;
    new mapgl.Polyline(map, {
        coordinates: segment.coords,
        width: 10,
        color: segment.color,
        width2: 14,
        color2: '#ffffff',
        zIndex,
    });

    if (segment.label) {
        const isFirstPoint = i === 0;
        const lastPointIndex = segment.coords.length - 1;
        const coords = isFirstPoint ? segment.coords[0] : segment.coords[lastPointIndex];

        new mapgl.CircleMarker(map, {
            coordinates: coords,
            radius: 16,
            color: '#0088ff',
            strokeWidth: 2,
            strokeColor: '#ffffff',
            zIndex: isFirstPoint ? 5 : 3,
        });

        new mapgl.Label(map, {
            coordinates: coords,
            text: segment.label,
            fontSize: 14,
            color: '#ffffff',
            zIndex: isFirstPoint ? 6 : 4,
        });
    }
});

You can find the full example below.

<!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="Car route geometry 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.30095449435502, 25.26873501453329],
                zoom: 17,
                key: 'Your API access key',
            });

            const segments = [
                {
                    color: '#e84646',
                    label: 'A',
                    coords: [
                        [55.29970489, 25.26853913],
                        [55.2994345, 25.26920691],
                        [55.29950714, 25.26936478],
                    ],
                },
                {
                    color: '#e3e340',
                    coords: [
                        [55.29950714, 25.26936478],
                        [55.30124581, 25.26959538],
                        [55.30141272, 25.26965618],
                        [55.30191503, 25.26896923],
                    ],
                },
                {
                    color: '#43e843',
                    label: 'B',
                    coords: [
                        [55.30191503, 25.26896923],
                        [55.3020634, 25.26892939],
                        [55.30233927, 25.26823968],
                    ],
                },
            ];

            segments.forEach((segment, i) => {
                const zIndex = segments.length - 1 - i;
                new mapgl.Polyline(map, {
                    coordinates: segment.coords,
                    width: 10,
                    color: segment.color,
                    width2: 14,
                    color2: '#ffffff',
                    zIndex,
                });

                if (segment.label) {
                    const isFirstPoint = i === 0;
                    const lastPointIndex = segment.coords.length - 1;
                    const coords = isFirstPoint
                        ? segment.coords[0]
                        : segment.coords[lastPointIndex];

                    new mapgl.CircleMarker(map, {
                        coordinates: coords,
                        radius: 16,
                        color: '#0088ff',
                        strokeWidth: 2,
                        strokeColor: '#ffffff',
                        zIndex: isFirstPoint ? 5 : 3,
                    });

                    new mapgl.Label(map, {
                        coordinates: coords,
                        text: segment.label,
                        fontSize: 14,
                        color: '#ffffff',
                        zIndex: isFirstPoint ? 6 : 4,
                    });
                }
            });
        </script>
    </body>
</html>