U_plus_200B
U_plus_200B

Reputation: 5

Leaflet bounds on layer prevent loading beyond anti-meridian

I'm currently working on a leaflet map, where the provided tiles are limited to certain regions. To prevent the loading of missing tiles I've added bounds to the layers like so:

layer.options.bounds = latLngBounds

The bounds for that specific region go from lng -200 to -20.

Now the problem is, that it does indeed prevent loading tiles outside of the bounds, but it also doesn't load the tiles from -200 to -180. So far I've tried to make the coordinates positive, adding offsets, other tiles, adding the bounds when creating the layers and using a L.latLngBounds instead of a simple array.

Is there a way to tell leaflet to go over the anti-meridian?

Here is a snipped that shows the problem with a live example:

var latLon = [40, -100]

const tileW = 22.5

const corner1 = L.latLng(-66.51, -202.5)
const corner2 = L.latLng(66.51, -22.5)
const latLngBounds = L.latLngBounds(corner1, corner2)

var map = L.map('map', {minZoom: 2}).setView(latLon, 2)
       
var osm = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    maxZoom: 19,
    attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
    bounds: latLngBounds
});
            
osm.addTo(map)

// Expected map position
L.marker(latLngBounds.getNorthEast()).addTo(map)
L.marker(latLngBounds.getSouthWest()).addTo(map)
L.marker(latLngBounds.getNorthWest()).addTo(map)
L.marker(latLngBounds.getSouthEast()).addTo(map)

// Antimeridian
L.marker([0, -180]).addTo(map)
#map { height: 90vh; }
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"
   integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A=="
   crossorigin=""/>
    <script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"
   integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA=="
   crossorigin=""></script>
</head>
<body>
     <div id="map"></div>
</body>
</html>

Upvotes: 0

Views: 477

Answers (1)

Falke Design
Falke Design

Reputation: 11378

You need to change the function where leaflet check if the tile is in the bounds:

L.BoundsTiles = L.TileLayer.extend({
            _isValidTile: function (coords) {
                var crs = this._map.options.crs;

                if (!crs.infinite) {
                    // don't load tile if it's out of bounds and not wrapped
                    var bounds = this._globalTileRange;
                    if ((!crs.wrapLng && (coords.x < bounds.min.x || coords.x > bounds.max.x)) ||
                            (!crs.wrapLat && (coords.y < bounds.min.y || coords.y > bounds.max.y))) { return false; }
                }

                if (!this.options.bounds) { return true; }

                // don't load tile if it doesn't intersect the bounds in options
                var tileBounds = this._tileCoordsToBounds(coords);
                var bounds = L.latLngBounds(this.options.bounds);
                if(!bounds.overlaps(tileBounds)){
                    var bounds2 = L.latLngBounds([bounds._southWest,bounds._northEast]);
                    bounds2._southWest.lng += 360;
                    bounds2._northEast.lng += 360;
                    return bounds2.overlaps(tileBounds);
                }
                return L.latLngBounds(this.options.bounds).overlaps(tileBounds);
            },
})


var osm = new L.BoundsTiles('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
            maxZoom: 19,
            attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
            bounds: latLngBounds
});

https://jsfiddle.net/falkedesign/8j6g5p07/

Upvotes: 0

Related Questions