地图就绪前,如何将瓦片坐标(x/y)转换为经纬度?
问题
我有一个自定义图层,需要将请求的瓦片坐标转换为经纬度。
L.GridLayer.CanvasCircles = L.GridLayer.extend({ createTile: function (coords) { console.log("coords", coords); if (window.map && window.map.layerPointToLatLng) { let latLng = window.map.layerPointToLatLng(coords); console.log("latLng", latLng); } else { console.log("No latLng yet"); } ... }
遗憾的是,map.layerPointToLatLng()(及其逆方法)仅在地图创建完成后才可使用。
// Create the overall Leaflet map using the two layers we created. let map = window.map = new L.Map('map', { center: centre, zoom: 15, layers: [baseLayer, heatmap] })
创建地图时会调用自定义图层中的createTile()方法,但此时地图尚未就绪,导致地图首次显示时自定义图层为空白。请问如何解决该问题?是否存在独立于地图实例的经纬度/缩放级别(z)与x/y坐标互转函数?
解决方案
方法一:延迟添加自定义图层,等待地图就绪
不要在初始化地图时直接将自定义图层传入layers选项,而是等地图完成初始化后再添加:
let map = window.map = new L.Map('map', { center: centre, zoom: 15, layers: [baseLayer, heatmap] }); // 监听地图加载完成事件,再添加自定义图层 map.on('load', function() { map.addLayer(new L.GridLayer.CanvasCircles()); });
这样createTile()会在地图完全就绪后才被调用,此时map.layerPointToLatLng()可以正常使用。
方法二:使用Leaflet独立的坐标转换工具函数
Leaflet提供了不依赖地图实例的坐标转换方法,通过L.CRS(坐标参考系统)实现,默认采用L.CRS.EPSG3857(Web墨卡托投影,多数瓦片地图的标准):
瓦片坐标(x,y,z)转经纬度
// coords为瓦片对象,包含x、y、z属性 const crs = L.CRS.EPSG3857; // 获取瓦片左上角的全局像素坐标 const tileOriginPoint = L.point(coords.x * 256, coords.y * 256); // 转换为经纬度 const latLng = crs.pointToLatLng(tileOriginPoint, coords.z);
如果需要瓦片中心的经纬度,调整像素坐标即可:
const centerPoint = L.point(coords.x * 256 + 128, coords.y * 256 + 128); const centerLatLng = crs.pointToLatLng(centerPoint, coords.z);
经纬度转瓦片坐标(x,y,z)
const latLng = L.latLng(39.9042, 116.4074); // 示例经纬度 const zoom = 15; const crs = L.CRS.EPSG3857; const point = crs.latLngToPoint(latLng, zoom); const tileX = Math.floor(point.x / 256); const tileY = Math.floor(point.y / 256);
方法三:在自定义图层中监听地图关联事件
如果必须在初始化时添加图层,可以在自定义图层中监听add事件,确保获取到地图实例后再处理瓦片:
L.GridLayer.CanvasCircles = L.GridLayer.extend({ onAdd: function(map) { L.GridLayer.prototype.onAdd.call(this, map); this._map = map; // 地图关联后触发重绘 this.redraw(); }, createTile: function (coords) { if (!this._map) { // 地图未就绪时返回空白瓦片 const tile = L.DomUtil.create('canvas', 'leaflet-tile'); tile.width = tile.height = 256; return tile; } // 此时this._map已就绪,可正常使用转换方法 const latLng = this._map.layerPointToLatLng(coords); // 后续绘制逻辑... const tile = L.DomUtil.create('canvas', 'leaflet-tile'); tile.width = tile.height = 256; // 在canvas上绘制内容 return tile; } });
这种方式下,即使初始化时图层被添加,也会先返回空白瓦片,等地图关联完成后触发重绘,生成正确内容。
内容的提问来源于stack exchange,提问作者fadedbee
相关产品推荐
相关产品推荐

