Looped map | MapGL | Urbi Documentation
MapGL JS API

Looped map

You can manage the looped map mode that enables moving and building geometries through the 180th meridian (antimeridian). If the mode is enabled, you can endlessly move the map along the equator. This function is available for MapGL JS API version 1.47.0 or higher.

To enable the looped map mode, pass the true value to the loopWorld property of MapOptions:

const map = new mapgl.Map('container', {
    center: [55.31878, 25.23584],
    zoom: 2,
    key: 'Your API access key',
    loopWorld: true,
});

You can also enable and disable the mode on the fly using the setOption map method:

// Enable looped map mode
map.setOption('loopWorld', true);

// Disable looped map mode
map.setOption('loopWorld', false);
<!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="A looped map 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: 2,
                key: 'Your API access key',
                loopWorld: true,
            });
        </script>
    </body>
</html>

If the looped map mode is enabled, geometries from user data sources (GeoJsonSource, RasterTileSource, and others) will also be spread across all map replicas beyond the 180th meridian.

<!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="A looped data sources on the map 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: [134.42, 2.18],
                zoom: 2,
                key: 'Your API access key',
                loopWorld: true,
            });

            const data = {
                type: 'FeatureCollection',
                features: [
                    {
                        type: 'Feature',
                        properties: {
                            layer: 'line',
                        },
                        geometry: {
                            type: 'LineString',
                            coordinates: [
                                [-225.2508687122533, -26.197140953800826],
                                [-97.63368123845338, 39.02575847482353],
                                [-51.930556221990116, -14.351992564255312],
                                [13.811631238563326, 48.86305468578952],
                                [106.27256872796717, 34.81173148148569],
                                [252.68117844115423, 56.09275343428385],
                            ],
                        },
                    },
                    {
                        type: 'Feature',
                        properties: {
                            layer: 'polygon',
                        },
                        geometry: {
                            type: 'Polygon',
                            coordinates: [
                                [
                                    [87.18727112357627, 44.44853501098232],
                                    [143.37332863083012, 62.289485224316415],
                                    [208.41239108206506, 62.452519937042204],
                                    [222.12332858591037, -18.935185937787594],
                                    [85.01395365634146, -31.01321448953935],
                                    [87.18727112357627, 44.44853501098232],
                                ],
                            ],
                        },
                    },
                    {
                        type: 'Feature',
                        properties: {
                            layer: 'marker',
                            label: 'A marker',
                        },
                        geometry: {
                            type: 'Point',
                            coordinates: [0, 0],
                        },
                    },
                    {
                        type: 'Feature',
                        properties: {
                            layer: 'marker',
                            label: 'Another marker',
                        },
                        geometry: {
                            type: 'Point',
                            coordinates: [220, 0],
                        },
                    },
                ],
            };

            new mapgl.GeoJsonSource(map, {
                data,
                attributes: {
                    type: 'geojson',
                },
            });

            new mapgl.RasterTileSource(map, {
                url: (x, y, zoom) => `https://tile.openstreetmap.org/${zoom}/${x}/${y}.png`,
                attribution:
                    '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
                attributes: { type: 'raster' },
            });

            map.on('styleload', () => {
                map.addLayer({
                    type: 'raster',
                    id: 'my-raster-tile-layer',
                    filter: ['match', ['sourceAttr', 'type'], ['raster'], true, false],
                    style: {
                        opacity: 0.75,
                    },
                });
                map.addLayer({
                    type: 'polygon',
                    id: 'my-polygon',
                    filter: [
                        'all',
                        ['match', ['sourceAttr', 'type'], ['geojson'], true, false],
                        ['match', ['get', 'layer'], ['polygon'], true, false],
                    ],
                    style: {
                        color: '#ff000044',
                    },
                });
                map.addLayer({
                    type: 'line',
                    id: 'my-line',
                    filter: [
                        'all',
                        ['match', ['sourceAttr', 'type'], ['geojson'], true, false],
                        ['match', ['get', 'layer'], ['line'], true, false],
                    ],
                    style: {
                        color: '#ffcd17',
                        width: 7,
                    },
                });
                map.addLayer({
                    type: 'point',
                    id: 'my-marker',
                    filter: [
                        'all',
                        ['match', ['sourceAttr', 'type'], ['geojson'], true, false],
                        ['match', ['get', 'layer'], ['marker'], true, false],
                    ],
                    style: {
                        iconImage: 'ent_i',
                        iconWidth: 25,
                        textField: ['get', 'label'],
                        textFont: ['Noto_Sans'],
                        textColor: '#0098ea',
                        textHaloColor: '#fff',
                        textHaloWidth: 1,
                        iconPriority: 100,
                        textPriority: 100,
                    },
                });
            });
        </script>
    </body>
</html>

Objects on the map are also spread across all map replicas except for HtmlMarker instances, which are not duplicated and are displayed according to the distance from the map center. Geometries of lines, polygons, and others can be built through the 180th meridian.

<!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="A looped objects on the map example" />
        <style>
            html,
            body,
            #container {
                margin: 0;
                width: 100%;
                height: 100%;
                overflow: hidden;
            }

            .popup {
                position: absolute;
                transform: translate(-50%, -100%);
                display: flex;
                flex-direction: column;
                min-width: 200px;
            }
            .popup-content {
                padding: 5px;
                border-radius: 4px;
                background: #fff;
                box-shadow: 0 1px 2px 0 rgba(38, 38, 38, 0.2);
            }
            .popup-tip {
                width: 0;
                height: 0;
                align-self: center;
                border-left: 10px solid transparent;
                border-right: 10px solid transparent;
                border-top: 10px solid #fff;
            }
        </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: [180, 0],
                zoom: 2,
                key: 'Your API access key',
                loopWorld: true,
            });

            new mapgl.Polygon(map, {
                coordinates: [[
                    [-218.89441752904858, 70.30565959814733],
                    [-225.925667557824, -45.73328345859119],
                    [-132.76160508486493, -14.81241744766605],
                    [-126.78504256222055, 58.15022232449164],
                    [-218.89441752904858, 70.30565959814733],
                ]],
                color: '#00FF0044',
                strokeColor: '#00ff00',
            });

            new mapgl.Polyline(map, {
                    coordinates: [
                        [-223.46245108836405, -26.918360474783015],
                        [-186.8219637290612, 3.7079820374058414],
                        [-128.74592895322968, 37.040091496754826],
                        [-73.69682609848928, 51.05782228027315],
                        [-12.524951100324575, 57.78845028707578],
                        [56.02973638807563, 61.681423620684775],
                        [160.94514533960353, 63.65208904762537],
                        [259.0310828109286, 65.02205304070272],
                    ],
                    dashLength: 10,
            });

            new mapgl.Marker(map, {
                coordinates: [-235.06629252685886, 57.7772495365397],
                icon: 'https://docs.2gis.com/img/mapgl/marker.svg',
            });

            new mapgl.Marker(map, {
                coordinates: [216.33995744596837, -35.920495472932814],
                label: {
                    text: "The marker's label",
                    offset: [0, 25],
                    relativeAnchor: [0.5, 0],
                    image: {
                        url: 'https://docs.2gis.com/img/mapgl/tooltip-top.svg',
                        size: [100, 50],
                        stretchX: [
                            [10, 40],
                            [60, 90],
                        ],
                        stretchY: [[20, 40]],
                        padding: [20, 10, 10, 10],
                    },
                },
            });

            new mapgl.HtmlMarker(map, {
                coordinates: [170, 0],
                html: `<div class="popup">
                    <div class="popup-content">
                        This is a text of the popup
                    </div>
                    <div class="popup-tip"></div>
                </div>`,
            });
        </script>
    </body>
</html>