目录
前言
一、后台数据服务设计
1、数据库查询
2、模型层对象设计
3、业务层和控制层设计
二、Echarts前端配置
1、地图的展示
2、次数排名统计
三、最终结果展示
1、地图展示
2、图表展示
总结
前言
在之前的博客中基于SpringBoot和PotsGIS的各省地震震发可视化分析,在这篇博客中采用二维地图的展现形式对全国各省的地震震发情况进行了综合展示。博客发布之后,有小伙伴找到博主说,对于Leaflet等地图可视化框架不熟悉,能不能使用echarts进行替代方案开发。同时在地图分析的同时,能否加上一些统计图表,让数据更加直观。在此基础上,就有了本文编写的初衷。
本文主要面向对于Leaflet等gis可视化框架不熟悉的朋友,在不使用gis可视化框架的同时进行地图应用的开发。本文将重点讲解如何使用SpringBoot进行后端接口的开发,基于后端java语言,直接构造前端echarts图表展示需要的数据。文章的最后,我们会输出一个使用Echarts开发的全国各省地震震发情况统计图、全国地震次数排名前10名和倒数10名(相对安全)的省份以及完整的统计数据列表。虽然在之前的博客中也对echarts组件进行了一些介绍,温故而知新,这里不仅回顾了一些地图开发的基础知识,同时结合地震各省份分布统计的需求场景更加有助朋友们理解。
一、后台数据服务设计
后台数据主要用于为前端提供数据来源,将各省份的地震震发数据从数据库中查询出来,然后以json的形式为前端提供。闲言少叙,下面直接进行正式的代码编写。基础采用的技术框架都是熟悉的框架,在之前的博客中也对开发框架进行了介绍,不再赘述。
1、数据库查询
为了能实现全国各个省份数据和地震信息进行关联查询,同时根据省份编码进行分组查询。这里涉及的表有两张。第一张是biz_province(全国省份行政区划信息表),另一张表是我们之前采集的biz_earthquake_info(地震信息表)。通过空间计算,将地震信息表中的位置和省份表进行包含计算,将地震信息包含在省份面中纳入所属省份口径。
图 1 省份信息表
图2 地震信息表
我们使用一下语句进行空间计算和分组统计计算:
select p.code data_id,max(p.name) data_name,count(1) data_value from biz_province p,biz_earthquake_info t where st_contains(p.geom, ST_GeomFromText(format('point(%s %s)',t.eq_lng,t.eq_lat),4326)) group by p.code order by data_value desc;
将以上的sql语句在数据库中执行以后可以得到一下结果:
2、模型层对象设计
模型层对象主要包括统计的视图对象即VO,还有业务层对象,比如数据访问层对象和业务对象。数据访问层对象将数据库中查询的结果写入到视图对象中。首先来看一下视图对象的定义,为了方便在echarts中进行展示,我们将展示的值分成统计指标、唯一id、统计指标值。对应的视图对象如下,这个类其实是通用的,一般的统计值都可以用这个视图对象来接收值:
package com.yelang.project.extend.earthquake.domain; import java.io.Serializable; import java.math.BigDecimal; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import lombok.ToString; @NoArgsConstructor @AllArgsConstructor @Setter @Getter @ToString public class EarthQuakeProvinceStatVO implements Serializable{ private static final long serialVersionUID = 5394617081879927259L; private String dataId; private String dataName; private BigDecimal dataValue; }
定义好了视图对象之后,我们还需要将数据库的sql语句在代码中执行,在数据访问层中执行以下代码完成数据访问。从性能的角度考虑,我们可以把这个查询结果进行缓存,在下一次数据展示的时候可以提高访问速度,这里为了减少不必要的代码,咱不提供实现。
static final String FIND_EARTH_QUAKE_LIST = "" + "select p.code data_id,max(p.name) data_name,count(1) data_value from biz_province p,biz_earthquake_info t where " + " st_contains(p.geom, ST_GeomFromText(format('point(%s %s)',t.eq_lng,t.eq_lat),4326)) " + " group by p.code order by data_value desc " + ""; /** * 全国各省地震震发统计 * @return */ @Select(FIND_EARTH_QUAKE_LIST) List findEarthQuakeStatList();
3、业务层和控制层设计
相对而言,这里将重点介绍业务层的设计。我们将在后台采用com.github.abel533.echarts组件直接生成前端所需要的echarts数据。两个省份地震次数排名柱状统计图几乎是一致的。在这里将生成图表数据的方法统一封装出来,根据不同的数据源传入来生成。关键代码如下:
public String convert2ProvinceLine(List dataList) { String result = ""; GsonOption option = new GsonOption(); option.title().text("各省地震震发次数统计图(单位:次)"); option.tooltip().trigger(Trigger.axis); option.legend("地震次数"); option.legend().y(Y.bottom).padding(0); option.toolbox().show(true).feature(new MagicType(Magic.line, Magic.bar).show(true), Tool.saveAsImage); option.calculable(true); List provinces = new ArrayList(); List eqCounts = new ArrayList(); for (EarthQuakeProvinceStatVO vo : dataList) { provinces.add(vo.getDataName()); eqCounts.add(vo.getDataValue().intValue()); } CategoryAxis categoreAxis = new CategoryAxis(); categoreAxis.data(provinces.toArray()).axisLabel().interval(0).rotate(20); option.xAxis(categoreAxis); option.yAxis(new ValueAxis()); Bar bar = new Bar("地震次数"); bar.data(eqCounts.toArray()); bar.markPoint().data(new PointData().type(MarkType.max).name("最大值"), new PointData().type(MarkType.min).name("最小值")); bar.markLine().data(new PointData().type(MarkType.average).name("平均值")); option.series(bar); result = option.toString(); return result; }
两个生成前top10,和倒数top10的ehcarts数据方法如下:
@Override public String buildProvinceLineMaxTop10(List dataList) { List top10 = new ArrayList(10); for(int i =0;i dataList.size() - 11;i--) { top10.add(dataList.get(i)); } return convert2ProvinceLine(top10); }
二、Echarts前端配置
完事具备,只欠东风。在后端将相应的数据和接口都准备妥当之后,我们来进行前端的界面开发。对echarts进行初始化。在地图开发过程当中有一些需要注意的地方,一定需要注意。
1、地图的展示
地图的展示,这里采用echarts的map组件,因为在组件采用的时候已经默认注册了china这个图源。因此我们可以直接使用,而无需再次注入。首先需要定义map的挂载组件。
地图的展示元素设置好之后,需要采用javascript的方式对数据进行设置。下面是关键代码:
mapChart = echarts.init(document.getElementById("echarts-map-chart")); mapoption = { title : { text: '全国各省地震次数统计', subtext: '数源来源中国国家地震局,单位:次', x:'left' }, tooltip : { trigger: 'item' }, legend: { orient: 'vertical', x:'right', y:'center', data:['地震次数'] }, dataRange: { min: 0, max: 2300, x: 'left', y: 'bottom', text:['高','低'], // 文本,默认为数值文本 calculable : true }, toolbox: { show: true, orient : 'vertical', x: 'right', y: 'bottom', feature : { mark : {show: true}, dataView : {show: true, readOnly: false}, restore : {show: true}, saveAsImage : {show: true} } }, roamController: { show: true, x: 'right', mapTypeControl: { 'china': true } }, series : [ { name: '地震次数', type: 'map', mapType: 'china', roam: false, zoom:1.2,//视觉比例大小,1.2即为原有大小的1.2倍 itemStyle:{ normal:{label:{show:true}}, emphasis:{label:{show:true}} }, data:[] } ] }; initProvinceMap();//地图初始化
下面是地图初始化的核心逻辑,这里采用ajax的方式进行数据加载,先给出核心代码:
function initProvinceMap(){ $.ajax({ url: ctx + "eq/province/echartslist", data: {}, dataType : "json", success: function(serverdata){ if(serverdata != ""){ var serverJsonData = serverdata.data; var jsonData = new Array(); for(var i=0;i