APEX从18版本开始,一直自带地图组件。可以充分利用Oracle数据库Spatial(地理空间)数据类型,查询和展现复杂的地理空间数据。但是由于地理空间的数据(主要是坐标数据)整理,录入复杂,使得APEX早期版本的地图组件形同鸡肋,增加了开发难度,与APEX倡导的零代码开发的理念背道而驰。真的是食之无味,弃之可惜。幸运的是,Oracle在APEX21.1版本开始支持geojson的数据格式,可以直接在网上扒下现成的geojson数据并导入到Oracle数据库中,然后可以灵活开发各种地理空间数据的应用。终于免去了自制地理数据之苦。先看看做出来的一个简单例子的效果:用热力图显示上海市各行政区2020年的GDP。
一、关于Geojson
关于geojson的数据格式和构成,请自行找度娘补课,不在本文展开讲述。APEX主要通过三种数据类型存放地理空间数据:
NUMBER:存放的坐标数据。必须同时两个NUMBER数据类型,一个存放经度,一个存放纬度。用NUMBER可以存放一些简单的“点”数据;
CLOB或VARCHAR2:存放geojson数据。导入的geojson数据可以直接使用。但如果要实现更灵活更复杂的展现和查询功能,建议转换成Oracle数据库的SDO_GEOMETRY
Spatial/SDO_GEOMETRY:Oracle数据库自带的对象数据类型,提供灵活且强大的地理空间数据的查询和展现。
如何把geojson数据转换成SDO_GEOMETRY数据,如何维护(例如:创建索引,复杂查询)等进阶使用,之后另开篇幅,深入讲述。
二、获取GEOJSON的数据
国内的geojson数据找度娘,国外的geojson找必应或放狗(也许需要翻墙)。
本文所用到的geojson数据来源于:https://datav.aliyun.com/tools/atlas/index.html。但这个数据有3个问题:
只到县区一级。例如:上海是黄浦区,广州市荔湾区...
只能抓两级数据。例如只能抓省市,或市区(县)两级数据,而不能抓省市区三级数据。
区域(多边形)中心“点”坐标数据,不是以类型(type)类型存放,而是以属性(properties)类型存放。导致导入geojson数据的时候不能被正确识别为地理空间数据。导致“点”数据导入时丢失。这是个坑,解决的办法是:不用APEX数据工作室里自带的导入工具。自己做一个定制化的导入工具,识别并导入“点”数据。“点”数据是经常被用到的。例如上面的热力图,APEX就要求必须是基于“点”数据展现。
打开下载的数据,可以看到中心“点”的(坐标)数据以嵌套的方式放在属性(properties)里。在用APEX数据工作室导入的时候,不能被识别而丢失。
APEX导入geojson数据的时候,没有“center”数据。
因为只是测试演示用,所以我就没有做定制化的导入工具,直接在表里增加了两个NUMBER字段,把中心“点”的经度和纬度坐标直接手工录入。然后还增加了两个字段,分别存放上海各行政区的2020年GDP和常住人口数据。
三、做一个基础图层。
APEX支持地图的多图层的查询和展现。
我们先在一个空白页上做一个基础图层。我们先要设置好地图的全局属性。选中地图组件,在右边设置栏里选中属性(Attribute)。
在地图背景里课选择“默认”,或者“定制”。定制里主要有两类地图背景可选,一类是OpenStreet地图,另一类是Oracle基于Here的地图。由于Here的地图久没更新(更新至2017年),所以建议还是使用OpenStreet地图(默认就是OpenStreet)。目前还不知道如何导入其它地图。
接下来是其它一些属性的设置。在“控件”一栏里,选中下图中的这些选项就够用了。
注意:地图的初始位置设定。
APEX可以通过查询的地理信息数据进行初始位置的中心定位。但是这个查询定位只支持SDO_GEOMETRY数据类型,不支持以CLOB数据类型存放的geojson数据。所以,在本例中使用了静态的经纬度数据(上海市黄浦区的中心点的经纬度,因为上海市的市中心点人民广场是在黄浦区嘛)来做地图的初始位置设定。另外,设置初始缩放级别为8(1~18,1为最小,18为最大)。8是试验下来的最合适的占屏值。
下面,来做第一个图层:基础图层。按照下面的截屏做好设置。基础图层一般都是用多边形的geojson数据。然后在“列映射”里指定几何结构数据类型(geojson,SDO_GEOMETRY,经纬度)。在这个例子里,因为我们导入的是geojson数据,以CLOB的数据类型存放,所以数据类型选择geojson。geojson列名(CLOB数据列)。别忘了要定义主键列。
接下来定义“外观”和“信息窗口”。这里主要是显示地图颜色外观和点击具体地图对象是所要显示的信息。例子里要显示的行政区名字。大家可以尝试不同的设置来看一下效果。
做好后,运行一下。展现的效果如下图:
四、做叠加图层
接下来,我们做两个叠加图层。以“热图”的方式,展现上海各行政区的GDP和人口数据。这里要注意的是,“热图”是“点”数据,必须要有坐标点类型的数据。前文讲过,本例中,把各行政区的中间点坐标(经度和纬度)是手工录入到两个NUMBER数据列里。所以在“列映射”里,选取的是“经度/纬度”,然后选择对应的数据列。另外,在外观的配色方案里,可以有多种配色可选。
做好后,运行的效果如下图:
同样的方式,做上海各行政区的人口热图如下:
五、显示更多信息
可以在“信息窗口”里选用“高级格式”。然后用HTML表达式引用多个SQL里的多个查询返回值。
注意:SQL查询语句里,列名一定要用大写, 并在HTML里引用。采用小写或者大小写混合都不能正确显示查询返回值,只会显示列名(严重怀疑这是APEX的bug)。
下图为信息窗口的显示效果。
六、点击区域归中
当鼠标点击某个特定的区域(坐标)的时候,这个区域(坐标)会自动移动到整个地图的中间。这个是通过动态操作(Dynamic Action)调用javascript实现。
先给地图设置一个静态ID,以作为在javascript里可以引用的地图区域的参数。
然后创建一个动态操作,当发生“单击地图区域”事件的时候,执行一段javascript。具体如下:
Javascript脚本如下:
const { lng, lat } = this.data;
apex.region("custom-map-region").call( "getMapObject" ).flyTo({
center: [ lng, lat ],
screenSpeed: 0.8
});
效果如下图:
本文到此,仅介绍了APEX地图组件的入门简单开发。大家可以点击下面链接,体验一下上述的测试案例(此测试案例仍在持续开发中,有可能部分功能暂时无效)。
https://apex.oracle.com/pls/apex/xxu/r/%E5%9C%B0%E5%9B%BE%E6%B5%8B%E8%AF%95%E6%A1%88%E4%BE%8B/%E4%B8%8A%E6%B5%B7%E5%B8%82%E8%A1%8C%E6%94%BF%E5%8C%BA?session=14826605763432
用户名:test,登录密码:test12345.
关于APEX地图进阶开发,下次将另起篇幅讲述。敬请关注。
===== End =====
更多Oracle APEX的知识和技巧,请猛戳下面二维码持续关注微信公众号“APEX中文社区”和“徐大爷的学习笔记”。
APEX中文社区
徐大爷的学习笔记