我使用Leaflet.js作为基于桌面和移动浏览器的 Map ,并且需要支持各种 Map 图块服务 . 其中一些切片服务使用粗略缩放级别(如1,5,10,15)定义,如果我请求不受支持的缩放级别,则服务不会返回切片 . (例如,如果我在不支持缩放级别 6
时请求 service/tiles/6/x/y
) .
Leaflet tile layers支持 minZoom
和 maxZoom
,但我想弄清楚是否有最佳做法来进行粗略缩放级别,以及其他人是否遇到过此问题 .
我在GitHub上发现这篇文章解决了不支持的缩放级别的平铺缩放:https://github.com/Leaflet/Leaflet/pull/1802
但我不确定这是否适用 . (我不确定我是想缩放还是“补间”缩放级别......但如果这很有意义并且不太困难,我愿意尝试 . )
我已经开始尝试这种方法变得混乱,因为缩放会导致更多缩放,我必须将用户驱动的缩放与系统驱动的缩放区分开来:
// layer metadata (assumption: Levels is in ascending order of zoom)
var layerDef = { Title: 'Service lines', Levels: [10, 15, 19] };
// create Leaflet Tile Layer and show on map
var layer = L.tileLayer('://host/service/{z}/{x}/{y}');
layer.minZoom = layerDef.Levels[0];
layer.maxZoom = layerDef.Levels[layerDef.Levels-1];
layer.addTo(map);
// initialize lastZoom for coarse zoom management
var lastZoom = map.getZoom();
var userZoom = true;
// handle supported zoom levels when zoom changes
map.on('zoomend', function (e)
{
// get new zoom level
var z = e.target._zoom || map.getZoom();
if (userZoom) // assume user initiated this zoom
{
// is this zoom level supported?
var zIdx = $.inArray(z, layerDef.Levels);
if (zIdx === -1)
{
// zoom level is not supported; zoom out or in to supported level
// delta: < 0 for zoom out, > 0 for zoom in
var zDelta = z - lastZoom;
var zLastIdx = $.inArray(lastZoom, layerDef.Levels);
var newZoom = -1;
if (zDelta > 0)
{
// user zoomed in to unsupported level.
// zoom in to next supported level (rely on layer.maxZoom)
newZoom = layerDef.Levels[zLastIdx + 1];
}
else
{
// user zoomed out to unsupported level.
// zoom out to next supported level (rely on layer.minZoom)
newZoom = layerDef.Levels[zLastIdx - 1];
}
if (newZoom !== -1)
{
userZoom = false; // set flag
setTimeout(function ()
{
map.setZoom(newZoom); // set zoom -- seems to not work if called from within zoomend handler
}, 100); // delay call to setZoom() to fix issue
}
}
}
else
{
userZoom = true; // clear flag
}
lastZoom = z;
});
(旁注:我希望粗缩放级别的原因是显而易见的:在每个缩放级别创建和存储光栅图块会很昂贵,特别是对于大型地理区域,尤其是与具有自己[本地]的离线移动设备一起使用时平铺服务器,有限的无线数据计划,有限的存储容量等 . 例如,这可能不是您可能会遇到的玩具应用程序和谷歌 Map ,而是特定于域和移动应用程序,其中空间和带宽非常宝贵 . )
谢谢!
UPDATE :我发现我使用此代码的问题是 map.setZoom(z)
在从 zoomEnd
处理程序中调用时无法正常工作(它确实设置了缩放,但导致显示灰色/不存在的图块问题,可能是因为Leaflet仍在缩放/缩放的过程) . 修复是使用 setTimeout
将调用延迟到 setZoom()
. 但是,我'm still really curious if anybody else has dealt with this, and if there is a '更好的方式'...(我更新了以上代码以使用 setZoom
修复)
2 回答
目前在GitHub上的Leaflet存储库中正在审核一个提交 . 它将zoomFactor添加到 Map 的选项中 . 也许这就是你要找的东西 . 至少,我认为只要您的可用tileset具有缩放级别(不知道这是否是正确的技术术语)是最低可用缩放级别的倍数,它就会起作用 .
见:https://github.com/Leaflet/Leaflet/pull/3285
以下(不保证,基于this)应与Leaflet v1.7.3一起使用,但可能不适用于当前的master .
它使用
serverZooms
选项将tile服务器上的可用缩放级别指定为有序数组 .覆盖
L.TileLayer._getZoomForUrl
以返回匹配或下一个较低的可用服务器缩放 . 还会覆盖L.TileLayer._getTileSize
以增加切片大小,以便在服务器缩放之间缩放切片 .