在Leaflet中使用多个切片图层时,避免加载不可见的切片

时间:2015-02-16 22:19:59

标签: leaflet

我正在使用Leaflet两个图块层。第一个,我将其称为地下室瓷砖图层,为整个世界提供图块。第二个覆盖在由弹跳选项定义的特定区域中的地下室图块层。我将这个称为覆盖图块层。在代码中,它如下所示:

var map = L.map('map');

// OpenstreetMap tile layer as basement
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
  attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);

// overlaying tile layer for specific region defined by bounds
L.tileLayer('http://{s}.examples.com/overlay/{z}/{x}/{y}.png', {
  bounds: L.latLngBounds(L.latLng(59.321966, 18.05943), L.latLng(59.328469, 18.076167));
}).addTo(map);

重叠的图块层不透明。因此,对于边界区域,仅覆盖的图块层的图块是可见的。不需要由地下室瓷砖层提供的瓷砖。但我还没有找到办法防止Leaflet装载这些不必要的瓷砖。我会很高兴任何提示。

我考虑过使用tile事件来中断不需要的tile的加载。但据记录的tile事件无法操纵tile加载。

这是展示行为的JSFiddle。如你所见tile 14/4825 / 6155.png从openstreetmap.org加载,即使它是不可见的。

在我的用例中,另一种想法使其更复杂:叠加地图具有严格的边界,因为它是由历史地图表生成的。因此,瓷砖在覆盖地图的边界处是透明的。在这些区域中,必须加载地下室地图的图块。

1 个答案:

答案 0 :(得分:3)

感谢@FrankPhillips在评论中的提示,我发现我可以从L.GridLayer覆盖_isValidTile方法来实现该功能。我可以添加 hole 选项作为 bounce 选项的反面。

L.ExtendedTileLayer = 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

            /*
             * this._globalTileRange is not defined
             * not quite sure why
             */
            var globalTileRange = this._map.getPixelWorldBounds( coords.z );

            var bounds = 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; }
        }

        var tileBounds = this._tileCoordsToBounds(coords);

        // don't load tile if it doesn't intersect the bounds in options
        if (this.options.bounds &&
            ! L.latLngBounds(this.options.bounds).intersects(tileBounds)) {
            return false;
        }

        // don't load tile if it does intersect the hole in options
        if (this.options.hole &&
            L.latLngBounds(this.options.hole).intersects(tileBounds)) {
            return false;
        }

        return true;
    },
});

var map = L.map('map', {
    center: [40.777838, -73.968654], 
    zoom: 14
});

new L.ExtendedTileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',{
    attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
    hole: L.latLngBounds(
        L.latLng(40.791853, -73.967128),
        L.latLng(40.781455, -73.955713)
    )
}).addTo(map);

L.tileLayer('http://tile.stamen.com/toner/{z}/{x}/{y}.png', {
    attribution: 'Map tiles by <a href="http://stamen.com">Stamen Design</a>, under <a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a>. Data by <a href="http://openstreetmap.org">OpenStreetMap</a>, under <a href="http://creativecommons.org/licenses/by-sa/3.0">CC BY SA</a>.',
    bounds: L.latLngBounds(
        L.latLng(40.791853, -73.967128),
        L.latLng(40.781455, -73.955713)
    )
}).addTo(map);

updated JSFiddle表明它正常运作。

_isValidTile大部分都是从Leaflet原版中复制而来。我不得不重新实现this._globalTileRange因为未定义。代码仅适用于leaflet-src.js,因为_isValidTime在生成版本中已被识别。