WebGIS开发系列教程(6):Openlayers之项目实战
本系列教程为webgis二维开发入门openlayers零基础小白学习教程,本篇为第六篇。
完整版可以滑到文末链接下载。
上一篇:
下一篇:
1.项目简介
本项目介绍的水利信息在线分析服务系统,采用广西 壮族自治区的水利信息相关数据,结合GIS的使用,通过地图标注、图表与动态推演等方式,直观模拟展现广西壮族自治区当前的水情 、雨情 状况,以及台风 情况。
2.系统需求
三大功能:
(1)工情查询 :水情信息、雨情信息的实时查询统计,以及地图标注定位,可以直观掌握每个水/雨情监测站点的水/雨情数据,全面掌握各地区的水情以及降雨情况。
(2)台风管理 :查询区域范围内相关的台风信息,即台风路径的查询以及线路的轨迹回放,根据台风数据确定相应的应对方案
(3)气象信息 :气象信息是影响水利工作的一个重要内容,相关部门可以对区域气象预报,卫星云图变化走势等数据进行分析,为防旱防涝工作提供辅助决策。
3.系统设计
3.1系统开发模式
springboot进行项目开发,在其静态文件夹static中引入openlayers的js文件和css文件即可使用openlayers

3.2项目的体系架构
该系统空间数据 为公共地图服务(天地图),业务数据 为与水利信息相关的业务数据,客户端(前端)使用openlayers5框架,后端 使用Java技术体系,最终构建成一个具有以下功能的WebGIS系统:
①地图显示与基本操作
②水/雨情信息的工情管理
③台风监测功能
④卫星云图气象信息功能
系统架构图为:

3.3系统功能

具体功能在项目中结合可视化界面和代码逻辑说明
4.数据组织设计
本项目涉及两大类数据:空间数据和属性数据
空间数据 :系统使用天地图(矢量底图)作为底图,上层叠加水利信息相关的矢量点数据。
数据之间的关联:天地图为底图,上面叠加广西边界的数据(储存在项目中),再叠加水库/河流的矢量点(存储在关系型数据库oracle中)

广西边界数据:

5.数据库设计
sql文件(oracle)位置:

st_sitinfo_b:监测站点信息表
st_rsvr_r:水库信息表
st_river_r:河流信息表
一个监测站点,对应多个水库,一个水库属于一个监测站点,为一对多的关系
一个监测站点,对应多个河流,一个河流属于一个监测站点,为一对多的关系
st_soil_r:雨量信息表
一个监测站点,对应多个雨量,一个雨量属于一个监测站点,为一对多的关系
wind_basicinfo:台风基本信息表
wind_info:台风详细信息表
wind_forecast:台风预测信息表
由于我们dao层技术使用的是mybatis,所以尽量让数据库中表的名字和java实体类中的类名相同,其中对应的字段名也应该相同,可以方便我们之后的开发。(不相同也没关系,我们可以在mybatis的mapper配置文件中进行对应匹配)。
java中实体类如下:
st_sitinfo_b:
//监测站点信息表
@Repository
public class St_sitinfo_b {
private String ZHANMA; //站码
private String zhanming; //站名
private String DONGJING; //东经
private String BEIWEI; //北纬
private String HEMING; //河名
private String ZHANLEI; //站类
private String DISHI; //地市
private String FENJU; //分局
private String DIZHI; //地址
//省略无参有参构造器、getset方法、toString()方法
AI生成项目

st_rsvr_r:
@Repository
public class St_rsvr_r {
private String STCD; //站码
private String TM; //时间
private String RZ; //水位
private String INQ; //流量
private String OTQ; //保证/正常
private String W; //警戒
//一个水库对应1个监测站点,一个监测站点有多个水库
private St_sitinfo_b st_sitinfo_b;
//省略无参有参构造器、getset方法、toString()方法
AI生成项目

st_river_r:
//河流信息表
//一条河流对应一个监测站点,一个监测站点对应多条河流,将监测站点放入河流中
@Repository
public class St_river_r {
private String STCD; //站码
private String TM; //时间
private String RZ; //水位
private String OTQ; //保证/正常
private St_sitinfo_b st_sitinfo_b; //监测站点
//省略无参有参构造器、getset方法、toString()方法
AI生成项目

st_soil_r:
//雨量信息表
//一个雨量信息属于一个监测站点,一个监测站点包含多个雨量信息
@Repository
public class St_soil_r {
private String COL001; //站码
private Date COL002; //时间
private Float COL007; //雨量
private St_sitinfo_b st_sitinfo_b; //监测站点
//省略无参有参构造器、getset方法、toString()方法
AI生成项目

wind_basicinfo:
//台风基本信息表
@Repository
public class Wind_basicInfo {
private int WINDID; //台风编号
private String WINDNAME; //台风中文名称
private String WINDEND; //台风英文名称
//省略无参有参构造器、getset方法、toString()方法
AI生成项目
wind_info:
//台风详细信息表
@Repository
public class Wind_info {
private int WINDID; //台风编号
private String TM; //时间
private float JINDU; //经度
private float WEIDU; //纬度
private String WINDSTRONG; //风力
private String WINDSPEED; //风速
private String QIYA; //气压
private String MOVESPEED; //移动风速
private String MOVEDIRECT; //风向
private int SEVRADIUS; //半径1
private int TENRADIUS; //半径2
//省略无参有参构造器、getset方法、toString()方法
AI生成项目

wind_forecast:
//台风预测信息表
@Repository
public class Wind_forecast {
private int WINDID; //台风编号
private String FORECAST; //预报国家
private Date TM; //时间
private float JINDU; //经度
private float WEIDU; //纬度
private String WINDSTRONG; //风力
private String WINDSPEED; //风速
private String QIYA; //气压
private String MOVESPEED; //移动风速
private String MOVEDIRECT; //风向
private int SEVRADIUS; //半径1
private int TENRADIUS; //半径2
//省略无参有参构造器、getset方法、toString()方法
AI生成项目

5.springboot整合mybatis完成对所有表的增删改查
MyBatis 框架是一个持久层框架,是 Apache 下的顶级项目。Mybatis 可以让开发者的主要精力放在 sql 上,通过 Mybatis 提供的映射方式,自由灵活的生成满足需要的 sql 语句。 使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs 映射成数据库中的记录。
springboot整合mybatis的步骤:
(1)导入mybatis和数据库的相关依赖
(2)在application.properties中进行相关配置
映射文件的位置:在类路径(resources)下的mapper文件夹下的.xml文件

(3)基于xml文件的整合
例如:监测站点st_sitinfo_b信息查询
数据库:

实体类对应St_sitinfo_b(实体类中的属性名称与数据库中的字段名称保持一致)
St_sitinfo_bDao的写法:
★@Mapper 注解:让spring容器知道这是一个mapper类,可以不写.xml文件,直接在方法上使用@Select注解写sql语句,但是当sql语句较复杂时,写xml文件比较易读。
.xml文件的写法
测试类的写法:
测试结果:

此例子为最简单的mybatis的使用,后面涉及一对多的写法,在前端调用时再贴出代码。
6.系统环境说明
操作系统:Windows10
开发工具:idea
Web服务器:springboot中内嵌的tomcat
WebGIS API:Openlayers5.3.0
数据库:oracle
浏览器:Google
第三方资源:jQuery、Bootstrap、echart、Bootstrap-table、jQueryUI
该系统的客户端使用Bootstrap前端开源框架、并采用Bootstrap-table创建数据表格,采用echarts插件绘制统计图,改进了系统的可用性和用户体验,让客户端的呈现效果更加丰富。系统的后台数据服务采用java实现数据库交互,通过Ajax技术实现客户端与后台的数据交互,使用JSON格式的数据进行传输。
7.Jquery简介
jQuery就是一个由JavaScript编写的轻量库,简单的说就是封装了一些JavaScript的操作,所以使用jQuery比使用原生的JavaScript可以达到用更少的代码做更多的事的效果。
例如:
$("#div01") 就是 document.getElementById("div01"); //更简单的拿到html元素
jQuery中的基本选择器:
1、id选择器 $( "#id" ):
所谓id选择器,就是相当于JavaScript的getElementById()方法。语法:$( "#id" ),也就是说#号后面跟上要操作的标签的id的值即可。
**2、类选择器 ( ".class" ):** 就是通过标签的class属性来选择标签的选择器。语法:`( ".class" )`,也就是 . 后面跟上标签的class的值即可。
3、元素选择器 $( "element" ):
也就是直接通过标签名选择标签,比如$("p").css("border", "3px solid blue");就是通过jQuery的元素选择器选择到所有的p标签,然后改变其样式。
4、全选择器 $( "*" ): 顾名思义,全选择器就是选择所有的标签。
最基本的使用:
效果:点击html中的p,段落内容就会消失(hide)
8.Ajax简介
AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。
AJAX 不是新的编程语言,而是一种使用现有标准的新方法。
AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。
AJAX 不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。
工作流程:

实际使用中,一般使用Jquery与AJAX结合使用,更加方便。
以上前端代码,点击按钮,通过ajax发送/login的get请求,发送的数据在后端controller中进行改造,在success回调函数中取到data数据,进行alert
通过@RequestParam取到前端的传过来的数据name和password,在控制台输出

通过map传值,将改造后的数据传回前端,进行显示

明确ajax的作用(异步交互,更快渲染),及基本格式,能用后端Controller接受前端ajax传来的url,并在回调函数中处理返回的数据,进行渲染显示即可。一般与jquery结合使用。
9.项目具体内容
9.1 index.html页面介绍
页面所有内容:

(1)地图容器
id="map"是装载底图的容器,需要关联ol.map中的target元素,进行使用

实现popup标注有两部分,Popup标注的目标容器和相关元素
①Popup标注的目标容器:id="popup"的div层,其class设置为ol-popup,采用默认的Popup标注框样式,也可自定义其宽高、背景等样式
②Popup标注的关闭按钮:id="popup-closer"的div层,其class设置为ol-popup-closer,采用默认的关闭按钮样式,同样也可以自定义样式
③Popup标注的内容容器:id="popup-content"的div层,标注详细信息的内容将在此容器中显示

(2)系统logo及功能面板
采用bootstrap的栅格系统进行布局,放置一系统logo的图片,图片放在/static/images/logo.png
功能模板面板为4个复选框checkbox,点击相应复选框,会触发相应的创建对应表格函数
实时水情:changeSqtable()
实时雨情:changeYqtable()
台风路径:changeTftable()
卫星云图:wxytStateChange()

(3)表格面板
水库:触发showShuiku()函数
河流:触发showHeliu()函数
雨量信息:触发showTb_Ylxx()函数
各市最大雨量:触发showTb_Gszdyl()函数
量级统计:触发showTb_Ljtj()函数
(4)底图切换面板
点击对应的图片会触发changeLayer()函数,传入的参数为底图的索引
(5)图例面板

(6)卫星云图
9.2基本功能
(1)添加底图
本项目加载天地图的在线地图作为底图,默认显示天地图的矢量底图,通过底图列表实现切换天地图数据类型的功能。
加载天地图与其他公共地图类似,可基于天地图官网提供的取图地址,通过new XYZ创建数据源,然后创建图层new TileLayer,并将图层加载到map中显示
代码:
获取图层addBaseLayer函数:得到矢量、影像、地形图层及其对应的注记图层,将其放入到LayerArr图层组中,用于后续通过底图索引切换底图
CreteTDTLayer()函数:根据图层的url,创建图层,返回图层

(2)底图切换功能
(3)绘制轮廓线
数据为广西壮族自治区边界线的坐标,为了方便,直接用js对象存储即可,如下:
在init()函数中绘制边界线:
由于我们使用投影坐标系为projection: ol.proj.get('EPSG:3857'), 所有在绘制边界的时候我们需要将经纬度坐标转换为web墨卡托投影
lonLat2Mercator函数:

(4)实时水情
实时水情,即水情查询功能。可查询水库、河流两类的水情信息,信息如下:
| 序号 | 站名 | 站码 | 水位 | 警戒/汛眼 | 保证/正常高 | 流量 | 时间 | 地址 |
|---|---|---|---|---|---|---|---|---|
并在地图上用标注点显示,同时在右侧结果列表中显示其详细信息,效果如上表。当用户勾选功能面板上的"实时水情"复选框时,会显示水情信息表格和地图标注;当单击地图上某个标注点,或者选择右侧结果列表中某个信息项时,可将地图中心移动至标注点的坐标位置处,同时在上方弹出Popup标注,并在Popup标注框中显示当前监测站点的水位信息统计图及文字描述。
★实现实时水情模块的关键流程有三个步骤 :
(1)通过查询关系数据库 中的系统业务数据库(属性数据),可获得水库或河流监测站点的实时水情数据,以及监测站点的详细信息
(2)解析查询结果数据 ,在地图上添加标注点 ;利用Bootstrap-table创建结果表格,将监测站点的基本水情信息加载到表格中显示
(3)以Popup标注 实现查看监测站点详细信息的功能,需要再次查询数据库得到监测站点的详细水情数据
查询水情并创建结果表格
创建水情表格的代码:

初始化Table的关键参数:

后端通过Controller接受前端请求:
查询结果:

查询结果通过 @ResponseBody注解向前端传送JSON数据,然后渲染出来
★使用Bootstrap-table进行表格的展示,要求 ::Bootstrap-table的field字段要同返回的JSON结果字段相同,这样可自动将数据添加至表格中。

前端显示:

加载水情地图标注:
当用户勾选功能面板中的"实时水情"时,先将图例面板与水情结果表格设为可见(display:block),

接着通过addWaterMarker(resInfoArray,type)方法在地图上添加水情监测站点的标注点,包括水库与河流两种类别。resInfoArray是储存水情的结果数组,type用来表示标注的类型是水库还是河流
使用矢量图层的矢量点要素方式添加标注点功能,即统一创建一个矢量图层(sssqMarkerLayer),在矢量图层种分别加载水库与河流两种类别的矢量要素,并分别将两种类型的矢量要素存储到对应的缓存数组中,便于后续的清除操作。
上述代码在地图中添加了图标形式的矢量要素点,在实例化Feature是,通过经纬度创建点,然后还有自定义的属性信息。
效果如下:(通过不同的条件设置不同的图片,进而进行显示)

实现Popup标注
该系统中实时水情、实时雨情以及台风路径模块均涉及Popup标注功能,在此,在地图容器中统一使用一个Popup标注对象,此对象作为全局变量,根据不同类型信息动态设置Popup标注内容。因此,需要现在首页添加Popup标注的目标元素,以及在地图初始化函数中加载这个Popup标注对象
首页添加Popup标注的目标元素:
在init()函数中添加Popup标注对象
显示实时水情的函数
因为添加的标注是按一个站添加一个标注,所有标注弹出Popup是弹出一个站的信息,我们需要重新查询(更加站查询),发送的请求为:
var urlStr = encodeURI("/"+type+"/"+fInfo.st_sitinfo_b.zhanma);
根据站码查询:
Controller层需要使用Rest风格接收参数,通过@PathVariable注解将接受到的参数取到
mapper写法例如:
返回的数据全部在data中,我们根据需要取到所需的数据,然后封装到html元素中,最后通过
加入到Popup中
后面的代码是使用Echarts进行作图的。
效果:

