原文再续,书接上一回。本文讲述APEX地图组件的进阶开发。
一、geojson数据转换成Oracle数据库的GEOMETRY数据
首先为了能够实现更加复杂的查询和展现,我们要把上文中导入数据库的geojson转换成sdo_geometry数据类型并建立索引。
先在原来的表中增加一个sdo_geometry字段spatial_geo。存放“多边形”数据。(APEX的SQL工作室的对象浏览器里不能创建sdo_geometry类型的字段,所以只能用命令行的方式创建)。
alter table shanghai_geo add spatial_geo MDSYS.SDO_GEOMETRY
用sdo_util.from_geojson()函数把geojson字段转换并更新到spatial_geo中。
update shanghai_geo aa set spatial_geo = (select sdo_util.from_geojson(GEOMETRY) from shanghai_geo bb where aa.id = bb.id)
由于在APEX地图里,大部分的数据查询和展现都是基于“点”类型。所以再创建一个“点”类型数据spatial_point_geo。
alter table shanghai_geo add spatial_point_geo MDSYS.SDO_GEOMETRY
用Oracle数据库里通过多边形计算出中心点的spatial函数sdo_geom.sdo_centroid(),计算出中心点并更新到spatial_point_geo中。
update shanghai_geo set spatial_point_geo = sdo_geom.sdo_centroid( spatial_geo, 1 )
创建sdo_geometry元数据和索引。切记切记:不要用SQL工作室里的SQL命令创建元素据和索引(已知bug)。直接在SQL工作室的对象浏览器里点击右上角的“+”号,用引导方式创建空间索引。选中sdo_geometry字段后,剩下的就一路默认点下去就可以了。通过这种方式创建的索引,同时会更新表对应的geo元数据表user_sdo_geom_metadata。
做完以上的geojson到Oracle数据库的GEOMETRY之后,我们可以把之前做的APEX地图改成以SDO_GEOMETRY的数据类型查询和展现。
二、交互报表和地图联动
实现目的,当点击交互报表的特定数据行的时候,地图上对应的区域居中并显示相关数据。
第一步,建一个交互报表。以及一个隐藏项P3_ID用来传递参数;
第二步,建一个页级的全局函数showFeature();
function showFeature( pId ) {
apex.item( "P3_ID").setValue( pId );
apex.event.trigger( $("#custom-map-region"), "refresh_and_center" );
}
这里:
custom-map-region是上一篇微文的第六节中设置的地图上海市行政区的静态ID
refresh_and_center是后面要设置的动态操作的事件名
第三步,在交互报表的属性里定义一个链接列。当点击的这个链接的时候,调用showFeature(),传入当前列的主键“ID”。
第四步,我们要做一个“点”图层,用来定位选中的区域。
第五步,创建一个自定义的动态操作centre after refresh。当点击交互报表的数据行链接的时候,通过javascript要实现三个动作:1,刷新地图;2,选中的区域归中;3,显示信息窗口。
首先要注意动态操作中的“When”的设置。
“Custom Event”和“jQuery Selector”里的设置一定要和第二步里javascript的定义对应上。
然后,要运行的javascript脚本如下:
var lMapRegion = apex.region("custom-map-region"), //获取地图所在区域
lFeatureId = apex.item("P3_ID").getValue(), //获取区域ID
//
lCenterLayerId = lMapRegion.call("getLayerIdByName", "4search"), //获取需要展现中心点的图层的名称
lInfoLayerId = lMapRegion.call("getLayerIdByName", "ShanghaiRegion"), //获取需要展现信息标签的图层的名称
//
lCenterFeature = lMapRegion.call("getFeature", lCenterLayerId, lFeatureId ), //获取中心点信息
lInfoFeature = lMapRegion.call("getFeature", lInfoLayerId, lFeatureId ), //获取标签信息
lCurrentZoom = lMapRegion.call("getMapCenterAndZoomLevel").zoom, //获取缩放值
//
lPosition;
if ( lCenterFeature.geometry ) {
lPosition = lCenterFeature.geometry.coordinates;
lMapRegion.call( "closeAllInfoWindows" ); //刷新(关闭已有的信息标签)
lMapRegion.call( "setCenter", lPosition ); //中心点定位
lMapRegion.call( "setZoomLevel", 9 ); //设置缩放值
setTimeout( function() { //显示信息标签
lMapRegion.call(
"displayPopup",
"infoWindow",
lInfoLayerId,
lFeatureId.toString(),
false,
{lng: lPosition[0], lat:lPosition[1]}
) }, 200 );
}
完成后,效果如下图:
===== End =====
更多Oracle APEX的知识和技巧,请猛戳下面二维码持续关注微信公众号“APEX中文社区”和“徐大爷的学习笔记”。
APEX中文社区
徐大爷的学习笔记