如何将Leaflet中gdal2tiles切片地图坐标从0-20000转为-10000~10000?
解决Minetest与Leaflet坐标不匹配问题
问题本质
Minetest的坐标以地图中心为原点(范围-10000到10000),但你用gdal2tiles生成的瓦片在Leaflet里是从左上角(0,0)到右下角(20000,20000)的像素坐标,两者原点差了10000的偏移量,直接用CRS.SIMPLE没效果是因为没做坐标偏移转换。
具体解决步骤
1. 写个简单的坐标转换函数
直接把Minetest的正负坐标和Leaflet的像素坐标做偏移映射:
// 偏移量就是图片尺寸的一半,对应Minetest原点在图片中心 const OFFSET = 10000; // Minetest坐标 → Leaflet像素坐标(用于定位标记、设置视图) function mtToLeaflet(mtX, mtZ) { // 注意Leaflet的Y轴是向下的,所以Minetest的Z要取反 return [mtX + OFFSET, OFFSET - mtZ]; } // Leaflet像素坐标 → Minetest坐标(用于点击取坐标等场景) function leafletToMt(leafletX, leafletY) { return [leafletX - OFFSET, OFFSET - leafletY]; }
2. 重新初始化地图(用CRS.SIMPLE)
替换你原来的L.RasterCoords逻辑,直接用CRS.SIMPLE并设置正确的边界:
var minZoom = 0; var maxZoom = 9; var imgSize = [20000, 20000]; var map = L.map(mapid, { minZoom: minZoom, maxZoom: maxZoom, crs: L.CRS.Simple // 这次要生效了 }); // 设置地图最大边界,防止拖动超出图片范围 var southWest = map.unproject([0, imgSize[1]], maxZoom); var northEast = map.unproject([imgSize[0], 0], maxZoom); map.setMaxBounds(new L.LatLngBounds(southWest, northEast)); // 比如你原来的Spawn点是Leaflet坐标[9000,10554],转成Minetest坐标就是(-1000, -554) // 用自定义函数转换后设置视图 var spawnMtCoords = [-1000, -554]; var spawnLeafletCoords = mtToLeaflet(spawnMtCoords[0], spawnMtCoords[1]); map.setView(map.unproject(spawnLeafletCoords, 7), 7);
3. 调整图层生成逻辑
把你原来的layerGeoGlobal这类函数里的坐标转换换成自定义函数,比如生成Spawn标记:
function layerGeoGlobal(mtGeoInfo, map, color, iconType, prefix) { // 把Minetest坐标转成Leaflet像素坐标 var leafletCoords = mtToLeaflet(mtGeoInfo.x, mtGeoInfo.z); // 转成Leaflet的经纬度(CRS.SIMPLE下其实就是坐标映射) var latLng = map.unproject(leafletCoords, maxZoom); return L.marker(latLng, { icon: L.divIcon({ className: `${prefix}-${iconType}`, iconSize: [30, 30], html: `<i class="${prefix} ${prefix}-${iconType}" style="color:${color}"></i>` }) }).bindPopup(`Spawn: (${mtGeoInfo.x}, ${mtGeoInfo.z})`); }
4. 测试验证
加个点击事件看看坐标转换对不对:
map.on('click', function(e) { var leafletCoords = map.project(e.latlng, maxZoom); var mtCoords = leafletToMt(leafletCoords.x, leafletCoords.y); alert(`当前点击的Minetest坐标:X=${Math.round(mtCoords[0])}, Z=${Math.round(mtCoords[1])}`); });
为啥之前CRS.SIMPLE没用?
你之前只是加了CRS.SIMPLE但没改坐标转换逻辑,L.RasterCoords默认是把图片左上角当原点,而Minetest的原点在中心,必须补上10000的偏移才能让两个坐标系对齐。
内容的提问来源于stack exchange,提问作者Amelie
相关产品推荐
相关产品推荐

