Openlayers系列(一)关于地图投影相关错误的解决方案

在开发基于MongoDB的GIS系统时,遇到OpenLayers瓦片加载偏移问题,行列号计算错误。原因是数据源投影设置错误,应设为EPSG3857而非EPSG4326。解决方案是调整Layer的source投影坐标系。注意,OpenLayers的View Projection设置为4326或3857不影响数据加载,但坐标单位不同,需要使用ol.proj.transform进行转换。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景

近期开发以MongoDB为基础的分布式地理数据管理平台系统,被要求做一个简单的demo给客户进行演示。于是笔者便打算向数据库中存储一部分瓦片数据,写一个简单的存取服务器,使用Openlayers客户端加载瓦片进行展示。本来是个挺简单的功能,可是谁曾想,“打了一辈子鹰,却被鹰啄瞎了眼”。在使用Openlayers客户端进行瓦片加载时,出现了加载的瓦片偏移、行列号不正确的问题。

问题描述

如图所示,地图出现了上下偏移的问题,并且,这些瓦片的实际行列号与当前Openlayers计算的行列号并不一致。

Arcgis Server切出的行列号分别是

上面一行瓦片是:104/50,105/50,106/50/107/50

下面一行瓦片是:104/49,105/49,106/49/107/49

Openlayers计算得到的行列号分别是

上面一行瓦片是:104/18,108/18,108/18/107/18

下面一行瓦片是:104/19,105/19,106/19/107/19
这里写图片描述

猜测及思路

看到行列号及瓦片的偏移,笔者的第一反应是切片方案存在问题。经过排查此次使用的ArcGIS Server采用的切片方案时Google切片方案(EPSG3857&#x

### 使用OpenLayers实现离线地图功能 #### 安装依赖包 为了使用OpenLayers创建离线地图应用,首先需要安装必要的依赖项。推荐使用`npm`来管理这些依赖。 ```bash npm install ol @types/ol --save ``` 对于那些不希望通过构建工具链工作的开发者来说,也可以直接从CDN获取最新版本的OpenLayers库文件[^4]。 #### 缓存机制的选择 在考虑如何让地图数据能够在没有互联网的情况下访问时,有几种不同的策略可以选择: - **LocalStorage**: 对于小型应用程序而言简单易用,但是其存储空间有限制。 - **IndexedDB**: 提供更大的数据库容量以及更复杂的查询能力;适合较大规模的地图瓦片缓存需求。 - **Web SQL Database (已废弃)**: 虽然部分浏览器仍支持此API, 但由于已被W3C标记为不再维护的状态,在新的项目里应避免使用它作为主要解决方案[^2]。 #### 地图瓦片预加载与保存 为了让用户即使在网络状况不佳甚至完全没有网络连接的情况下也能正常浏览地图,提前下载并储存好所需的地理图像至关重要。这通常涉及到遍历定范围内的经纬度坐标,并请求相应的图片资源将其保存到本地存储中去。 下面是个简单的例子展示怎样利用JavaScript异步函数批量抓取指定区域内的所有切片并将它们放入IndexDB内: ```javascript async function preloadTiles(minX, minY, maxX, maxY){ const db = await openDatabase('mapCache', 'tiles'); for(let x=minX; x<=maxX; ++x){ for(let y=minY; y<=maxY; ++y){ try{ let response = await fetch(`https://example.com/tiles/${z}/${x}/${y}.png`); if(!response.ok) throw new Error("Failed to load tile"); let blob = await response.blob(); await saveToDb(db, `tile_${z}_${x}_${y}`,blob); }catch(error){ console.error(`Error loading or saving tile ${x},${y}:`, error.message); } } } } ``` 这段代码假设存在个名为`openDatabase()`的帮助方法用于打开或创建个新的IDB环境,还有另个叫作`saveToDb()`的方法负责把二进制对象写入特定键名之下。实际操作过程中可能还需要处理更多细节比如错误重试逻辑等。 #### 配置OpenLayers读取本地缓存的数据源 旦完成了上述准备工作之后,就可以配置OpenLayers实例指向本地而非远程服务器上的瓦片位置了。这里给出段基于之前提到过的自定义方案三中的思路改造而成的例子[^3]: ```javascript import Map from 'ol/Map'; import View from 'ol/View'; import TileLayer from 'ol/layer/Tile'; // ... other imports ... const mapProjection = "EPSG:900913"; // 假设这是目标投影系统 let source; if(navigator.onLine){ // 如果当前处于联网状态则尝试更新最新的在线版面 source=new XYZ({ url:'http://{a-c}.abc.com/{z}/{x}/{y}.png', crossOrigin:'anonymous' }); }else{ // 否则切换至预先准备好的脱机模式下工作 source= new Static({url:"offline_tiles/", projection:mapProjection}); } new Map({ target: document.getElementById('map'), layers:[ new TileLayer({source}) ], view:new View({ center:[0,0], zoom:2, projection:mapProjection }) }); ``` 在这个片段里面,当检测到设备具有可用网络链接时就会向官方服务端发起HTTP GET请求拉取消息体;反之如果发现断网情况发生的话就转而调用静态类构造器传入事先设定号的基础路径参数从而激活内部封装好了的相关行为动作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值