shapefile文件转geojson 加载到openlayers上使用

工作中经常需要预览shp文件,一般都是用arcmap、qgis之类桌面端软件操作。对于本机没有装软件的情况下,很难预览。因此在后台写了一个读取shp的服务,前端通过上传,实现读取shp,并在地图上展示位置和属性。

geotools 读取shp,并转为geojson格式

主要使用了geotools来进行读取数据:

引入依赖,这里使用最新版27-SNAPSHOT

<geotools.version>27-SNAPSHOT</geotools.version>
<dependency>
	<groupId>org.geotools</groupId>
	<artifactId>gt-main</artifactId>
	<version>${geotools.version}</version>
</dependency>
<dependency>
	<groupId>org.geotools</groupId>
	<artifactId>gt-shapefile</artifactId>
	<version>${geotools.version}</version>
</dependency>
<dependency>
	<groupId>org.geotools</groupId>
	<artifactId>gt-geojson</artifactId>
	<version>${geotools.version}</version>
</dependency>
<dependency>
	<groupId>cn.hutool</groupId>
	<artifactId>hutool-core</artifactId>
	<version>5.7.14</version>
</dependency>

geotools 主要代码


/**
 * shp转换为Geojson
 * @param file_
 * @return Map
 * @throws Exception
 */
@PostMapping("/shpToGeojson")
@ResponseBody
public Map<String, String> shpToGeojson(
        @RequestParam("shp") MultipartFile file_[]) throws Exception {
	
    Map<String, String> map = new HashMap<String, String>();
    //存放shp文件
    File[] targetFileForWrite = null;
    if (file_ != null && file_.length > 0) {
        //判断是否为压缩文件,目前只支持zip
        if (file_[0].getOriginalFilename().endsWith(".zip")) {
            File file = new File(FileUtil.getTmpDirPath(), "temp.zip");
            file_[0].transferTo(file);
            //使用hutool的解压功能
            File files = ZipUtil.unzip(file);
            targetFileForWrite = files.listFiles();
        } else {
            //创建临时文件路径
            String filePath = System.getProperty("java.io.tmpdir");
            targetFileForWrite = new File[file_.length];
            //获取shp文件
            for (int i = 0; i < file_.length; i++) {
                String tempName = file_[i].getOriginalFilename();
                File tempFile = new File(filePath, tempName);
                //获取父目录
                File fileParent = tempFile.getParentFile();
                if (!fileParent.exists()) {
                    if (!fileParent.mkdirs()) {
                        map.put("code", "500");
                        map.put("status", "failure");
                        map.put("message", "文件不存在!");
                        return map;
                    }
                }
                // 转存文件
                file_[i].transferTo(tempFile);
                targetFileForWrite[i] = tempFile;
            }
        }
    }

    //至少包含 dbf shp shx 三个文件
    if (targetFileForWrite == null || targetFileForWrite.length < 3) {
        map.put("code", "500");
        map.put("status", "failure");
        map.put("message", "请传入完整shp文件!");
        return map;
    }
    //shp 数据源
    ShapefileDataStore shpDataStore = null;
    try {
        // 获取shp数据源,这里用数组中任意一个文件即可读取所有文件
        shpDataStore = new ShapefileDataStore(targetFileForWrite[0].toURI().toURL());
        // 设置编码
        Charset charset = Charset.forName("UTF-8");
        shpDataStore.setCharset(charset);
        //获取feature对象组
        String typeName = shpDataStore.getTypeNames()[0];
        SimpleFeatureSource featureSource = null;
        featureSource = shpDataStore.getFeatureSource(typeName);
        //获取图形数组
        SimpleFeatureCollection result = featureSource.getFeatures();
        //将feature转为geojson
        StringWriter writer = new StringWriter();
        FeatureJSON json = new FeatureJSON();

        json.writeFeatureCollection(result, writer);

        map.put("code", "200");
        map.put("status", "success");
        map.put("message", writer.toString());
    } catch (Exception e) {
        map.put("code", "500");
        map.put("status", "failure");
        map.put("message", e.getMessage());
        e.printStackTrace();
    } finally {
      	//关闭数据源
        if (shpDataStore != null) {
            shpDataStore.dispose();
        }
        //删除临时文件
        for (File file : targetFileForWrite) {
            if (file != null && file.exists()) {
                file.delete();
            }
        }
    }
    return map;
}

前端请求服务,并使用openlayers展示数据

前端使用ajax发起请求,获取后台数据,并使用openlayers展示数据。

html 代码

使用form表单实现上传,可以根据项目选择上传方式。

<!--上传 form 和 input -->
<form id="form" method="post" enctype="multipart/form-data">
	<input  onchange="upload()" multiple="multiple" id="shp" type="file" name="shp"/>
</form>

js代码

为了方便使用openlayers,这里使用ES6方式实现。

引入依赖

// 引入依赖 start =================================================================
import GeoJSON from 'ol/format/GeoJSON';
import Map from 'ol/Map';
import View from 'ol/View';
import {Fill, Stroke} from 'ol/style';
import {OSM, Vector as VectorSource} from 'ol/source';
import {Tile as TileLayer, Vector as VectorLayer} from 'ol/layer';
// 引入依赖 end =================================================================
//实现方法
let upload = function() {
    // 使用formdata获取上传数据
    let formData = new FormData($("#form")[0]);
    //定位地图加载数据方法
    let toMap = function (features) {
        // 创建资源对象
        const vectorSource = new VectorSource({
            features: features,
        });
        // 创建图层对象
        const vectorLayer = new VectorLayer({
            source: vectorSource,
            //设置样式
            style: new Style({
                //边框样式
                stroke: new Stroke({
                    color: 'red',
                    width: 2,
                    lineDash: [3, 5]
                }),
                //填充样式
                fill: new Fill({
                    color: 'rgba(0, 0, 255, 0.3)',
                }),
            }),
        });
        // 创建地图对象
        const map = new Map({
            layers: [
                // 创建谷歌底图
                new TileLayer({
                    source: new OSM(),
                }),
                vectorLayer,
            ],
            // 地图容器div的id
            target: 'map',
            view: new View({
                // 定位中心点
                center: [0, 0],
                // 定位级别
                zoom: 2,
            }),
        });
    }
    //这里使用ajax请求数据,可根据项目调整。
    $.ajax({
        url: baseUrl + "/shpToGeojson",
        dataType: "json",
        type: 'POST',
        //使用 formdata 上传文件
        data: formData,
        cache: false,
        contentType: false,
        processData: false,
        async: true,
        success: function (data) {
            if (data.status == "success") {
                //将json字符串转为json对象
                let coordinate = JSON.parse(data.message);
                //判断geojson必有属性
                if (coordinate.features && coordinate.type) {
                    //openlayers 读取geojson数据,生成图形对象
                    let features = (new GeoJSON()).readFeatures(coordinate, {
                        dataProjection: 'EPSG:4326',  // 设定数据使用的坐标系
                        featureProjection: 'EPSG:3857' // 设定当前地图使用的feature的坐标系
                    });
                    //定义绑定事件
                    let clickFunc = function (e) {
                        //输出图形对象属性。
                        console.log(e.target.getProperties())
                    }
                    for (let i = 0; i < features.length; i++) {
                        const feature = features[i];
                        //绑定点击事件
                        feature.on('click', clickFunc);
                    }
                    //将图形对象添加到地图上
                    toMap(features)
                }
            }
        }
    });
}

示例展示

底图为天地图影像图,数据为北京市各区。左侧展示地图位置,右侧输出属性数据。

这里的属性数据,可以以弹出信息框的方式展示,效果更好,有时间更新。
在这里插入图片描述

参考网站:
[1]: openlayers官网读取geojson
[2]: geotools官网API FeatureJSON操作

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

非科班Java出身GISer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值