Рисование фигур | MapGL | 2GIS Documentation
MapGL JS API

Рисование фигур

На карте можно рисовать различные геометрические фигуры, такие как линии, круги и многоугольники.

Чтобы нарисовать на карте круг, нужно создать объект Circle и указать координаты центра и радиус в метрах. Дополнительно можно указать параметры обводки и используемые цвета (см. CircleOptions).

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>

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

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>

Чтобы нарисовать на карте многоугольник, нужно создать объект Polygon.

Координаты для многоугольника указываются в виде двумерного массива. Первый вложенный массив должен содержать координаты основных вершин многоугольника. Остальные вложенные массивы не обязательны и могут быть заданы для того, чтобы создать вырез внутри многоугольника (один дополнительный массив - один вырез в виде многоугольника).

Важно указать координаты таким образом, чтобы первое и последнее значение в каждом массиве совпадало. Иными словами, ломаная должна быть замкнутой.

Дополнительно можно указать цвет полигона и параметры обводки (см. PolygonOptions).

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: '#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>

Чтобы нарисовать на карте линию, нужно создать объект Polyline и указать координаты точек линии, цвет линии и толщину.

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>

У линии нет параметров обводки. Вместо этого, чтобы создать эффект обводки, можно нарисовать несколько линий друг под другом. При этом важно указать для линий параметр zIndex, чтобы они корректно наложились друг на друга.

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>

По умолчанию Polyline создаёт сплошную линию.

Чтобы создать штриховую линию, нужно указать следующие параметры:

  • dashLength - длина штрихов (в пикселях).
  • gapLength - длина пробелов (в пикселях). Если параметр не указан, длина пробелов будет равна длине штрихов.
  • gapColor - цвет пробелов. Если параметр не указан, пробелы будут полностью прозрачными.
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>

Опция renderingMode указывает на то, будет ли линия участвовать в буфере глубины.

Сравните поведение полилинии при переключении значения renderingMode на карте ниже. В режиме 3d вы увидите линию, которая будет скрываться за зданиями и другими объектами.

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

В режиме 2d вы увидите линию поверх всех объектов.

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>

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

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>

Чтобы подписаться на события, нужно использовать метод on() (см. DynamicObjectEventTable для полного списка событий).

Например, чтобы добавить обработчик для нажатия на круг, можно использовать следующий код:

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

Чтобы удалить фигуру, нужно использовать метод destroy(). См. Circle reference.

Например, чтобы удалить круг, можно использовать следующий код:

circle.destroy();

Если вы хотите удалить все добавленные фигуры, вам нужно удалять каждую фигуру индивидуально:

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

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

Сначала нужно создать массив, содержащий координаты и другую информацию о сегментах маршрута:

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

Затем нужно создать цикл, который создаст объект Polyline для каждого сегмента маршрута. При создании Polyline важно указать параметр zIndex, чтобы созданные линии корректно наложились друг на друга.

Дополнительно можно отметить начальную и конечную точки маршрута кругом (CircleMarker) и текстовой меткой (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,
        });
    }
});

Полный пример можно найти ниже.

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