当前位置: 代码迷 >> 综合 >> openlayers 加载shp文件到map上
  详细解决方案

openlayers 加载shp文件到map上

热度:92   发布时间:2023-12-03 09:17:07.0

要求:用户上传任意的shp文件,在地图上实现对该shp文件的预览

参考:https://openlayers.org/en/latest/examples/reprojection-by-code.html
https://github.com/mbostock/shapefile

开发环境:openlayers5

思路:
1)利用shapefile库,来解析shp文件,读取feature转换成geojson字符串
2)利用new ol.format.GeoJSON()读取feature
3)加载feature到地图上

实现:

<script src="https://unpkg.com/shapefile@0.6"></script>
<script>var source1 = new ol.source.Vector({wrapX: false});var vector = new ol.layer.Vector({source: source1});var geojsonformat = new ol.format.GeoJSON();initMap();//这里写自己的初始化map的代码   用到的shapefile.open("shp/polygon.shp","shp/polygon.dbf",{encoding:"utf-8"})//这里防止乱码,可以用encoding来指定文件的编码。.then(source => source.read().then(function log(result) {if (result.done) return;console.log(result.value);//result.value 为geojson文件var feature = geojsonformat.readfeature(result.value);sorce1.addFeature(feature);return source.read().then(log);})).catch(error => console.error(error.stack));
</script>

不足:该方法只能适用于shp文件已经提交到后台上,且可以被访问的情况下,才能加载成功。

打开https://unpkg.com/shapefile@0.6.6/dist/shapefile.js
发现open方法支持ArrayBuffer作为传入参数,此时,可以考虑使用FileReader对象来读取文件
在这里插入图片描述
代码修改为:

<script src="https://unpkg.com/shapefile@0.6"></script>
shp:<input type="file" id="file1" name="shpfile"/>
dbf:<input type="file" id="file2" name="dbffile"/>
<button onclick="readfile()">读取文件</button><script>var source1 = new ol.source.Vector({wrapX: false});var vector = new ol.layer.Vector({source: source1});var geojsonformat = new ol.format.GeoJSON();initMap();function readfile() {var shparray, dbfarray;//分别存取shp文件和dbf文件var shpfiles = $('#file1').prop('files');//获取到文件列表var dbffiles = $('#file2').prop('files');if (shpfiles.length == 0) {alert('请选择文件');} else {var reader = new FileReader();//新建一个FileReaderreader.readAsArrayBuffer(shpfiles[0]);//读取文件reader.onload = function (evt) { //读取完文件之后会回来这里shparray = evt.target.result;//evt.target.result 为ArrayBuffer形式的文件var reader2 = new FileReader();reader2.readAsArrayBuffer(dbffiles[0]);reader2.onload = function (evt) { //读取完文件之后会回来这里dbfarray = evt.target.result;shapefile.open(shparray, dbfarray, {encoding: "utf-8"}).then(source => source.read().then(function log(result) {if (result.done) return;var feature = geojsonformat.readFeature(result.value);source1.addFeature(feature);return source.read().then(log);})).catch(error => console.error(error.stack));}}}}
</script>

好了,这下可以不用先把shp文件上传到后端,直接在前端就能查看了。但是相对的,另一个问题就出来了,坐标系不对,客户给过来的文件投影坐标是EPSG:4214的,但是地图的投影坐标是EPSG:4326准确说,是openlayers只定义了EPSG:4326和EPSG:3857的两种坐标系,这真是一个巨大的坑。
好在官网给出的demo是利用proj4.js,自己定义EPSG:4214的投影坐标,然后注册到openlayers中,然后使用。

于是代码可以修改为:

<script src="https://unpkg.com/shapefile@0.6"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.5.0/proj4.js"></script>投影坐标:<input type="text" id="srs" name="srs"/>
编码:<input type="text" id="encoding" name="encoding" />
shp:<input type="file" id="file1" name="shpfile"/>
dbf:<input type="file" id="file2" name="dbffile"/>
<button onclick="readfile()">读取文件</button><script>initMap();function readfile() {var encoding = $("#encoding").val();var srs = $("#srs").val();if(srs == ""){return false;}var newProj;$.ajax({url:"https://epsg.io/?format=json&q="+srs,type:"get",dataType:"json",async:false,success:function(result){proj4.defs("EPSG:"+srs,result.results[0].proj4);ol.proj.proj4.register(proj4);newProj = ol.proj.get("EPSG:"+srs);}})var shparray, dbfarray;var shpfiles = $('#file1').prop('files');//获取到文件列表var dbffiles = $('#file2').prop('files');if (shpfiles.length == 0) {alert('请选择文件');} else {var reader = new FileReader();//新建一个FileReaderreader.readAsArrayBuffer(shpfiles[0]);//读取文件reader.onload = function (evt) { //读取完文件之后会回来这里shparray = evt.target.result;var reader2 = new FileReader();reader2.readAsArrayBuffer(dbffiles[0]);reader2.onload = function (evt) { //读取完文件之后会回来这里dbfarray = evt.target.result;shapefile.open(shparray, dbfarray, {encoding: encoding}).then(source => source.read().then(function log(result) {if (result.done) return;var feature = new ol.format.GeoJSON().readFeature(result.value, {dataProjection: newProj,featureProjection: 'EPSG:4326'});//投影转换dataProjection geojson中featue的投影坐标,featureProjection 目标投影坐标系feature.setStyle(style);source1.addFeature(feature);return source.read().then(log);})).catch(error => console.error(error.stack));}}}}
</script>

到此前端读取shp文件加载到地图中的代码完成了,如果只想读取shp文件,对应的有提供相对的方法,此处不做验证,希望是一致的在这里插入图片描述

  相关解决方案