在 Leaflet 中使用多个图块层时避免加载不可见图块
Avoid loading of invisible tiles when using multiple tile layers in Leaflet
我正在使用 Leaflet 和两个图块图层。第一个,我称之为 basement tile layer,为整个世界提供瓷砖。第二个覆盖由弹跳选项定义的特定区域中的地下室瓷砖层。我将其称为 叠加图块层 。在代码中,这类似于以下内容:
var map = L.map('map');
// OpenstreetMap tile layer as basement
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: '© <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 加载这些不必要的图块。如果有任何提示,我会很高兴。
我考虑过使用图块事件来中断加载不需要的图块。但据记录的图块事件无法操纵图块加载。
这里是 JSFiddle 演示行为。如你所见tile 14/4825/6155.png 是从 openstreetmap.org 加载的,即使它是不可见的。
在我的用例中,另一种想法使它变得更加复杂:叠加地图具有严格的边界,因为它是由历史地图生成的 sheet。因此,图块在叠加地图的边界处是透明的。在这些区域中,必须加载地下室地图的瓦片。
感谢@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
在生产构建中被丑化了。
我正在使用 Leaflet 和两个图块图层。第一个,我称之为 basement tile layer,为整个世界提供瓷砖。第二个覆盖由弹跳选项定义的特定区域中的地下室瓷砖层。我将其称为 叠加图块层 。在代码中,这类似于以下内容:
var map = L.map('map');
// OpenstreetMap tile layer as basement
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: '© <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 加载这些不必要的图块。如果有任何提示,我会很高兴。
我考虑过使用图块事件来中断加载不需要的图块。但据记录的图块事件无法操纵图块加载。
这里是 JSFiddle 演示行为。如你所见tile 14/4825/6155.png 是从 openstreetmap.org 加载的,即使它是不可见的。
在我的用例中,另一种想法使它变得更加复杂:叠加地图具有严格的边界,因为它是由历史地图生成的 sheet。因此,图块在叠加地图的边界处是透明的。在这些区域中,必须加载地下室地图的瓦片。
感谢@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
在生产构建中被丑化了。