0


基于SpringBoot和Echarts的全国地震可视化分析实战

前言

    在之前的博客中基于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 = "<script>"
            + "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 "
            + "</script>";
    /**
     * 全国各省地震震发统计
     * @return
     */
    @Select(FIND_EARTH_QUAKE_LIST)
    List<EarthQuakeProvinceStatVO> findEarthQuakeStatList();

3、业务层和控制层设计

    相对而言,这里将重点介绍业务层的设计。我们将在后台采用com.github.abel533.echarts组件直接生成前端所需要的echarts数据。两个省份地震次数排名柱状统计图几乎是一致的。在这里将生成图表数据的方法统一封装出来,根据不同的数据源传入来生成。关键代码如下:
public String convert2ProvinceLine(List<EarthQuakeProvinceStatVO> 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<String> provinces = new ArrayList<String>();
        List<Integer> eqCounts = new ArrayList<Integer>();
        
        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<EarthQuakeProvinceStatVO> dataList) {
    List<EarthQuakeProvinceStatVO> top10  = new ArrayList<EarthQuakeProvinceStatVO>(10);
    for(int i =0;i<10;i++) {
        top10.add(dataList.get(i));
    }
    return convert2ProvinceLine(top10);
}

@Override
public String buildProvinceLineMinTop10(List<EarthQuakeProvinceStatVO> dataList) {
    List<EarthQuakeProvinceStatVO> top10  = new ArrayList<EarthQuakeProvinceStatVO>(10);
    for(int i = dataList.size() - 1;i> dataList.size() - 11;i--) {
        top10.add(dataList.get(i));
    }
    return convert2ProvinceLine(top10);
}

二、Echarts前端配置

    完事具备,只欠东风。在后端将相应的数据和接口都准备妥当之后,我们来进行前端的界面开发。对echarts进行初始化。在地图开发过程当中有一些需要注意的地方,一定需要注意。

1、地图的展示

    地图的展示,这里采用echarts的map组件,因为在组件采用的时候已经默认注册了china这个图源。因此我们可以直接使用,而无需再次注入。首先需要定义map的挂载组件。
<div id="tab-1" class="tab-pane active">
    <div class="panel-body">
         <div class="row">
            <div class="col-sm-12">
                <div class="ibox float-e-margins">
                    <div class="ibox-content">
                         <div style="height:600px" id="echarts-map-chart"></div>
                    </div>
                </div>
            </div>
        </div>
      </div>
  </div>
    地图的展示元素设置好之后,需要采用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<serverJsonData.length;i++){
                                   var pname = serverJsonData[i].dataName;
                                   if(pname.indexOf("黑龙江") != -1 || pname.indexOf("内蒙古") != -1){
                                       pname = pname.substring(0,3);
                                   }else{
                                       pname = pname.substring(0,2);
                                   }
                                   jsonData.push({name: pname,value: serverJsonData[i].dataValue});
                               }
                            mapoption.series[0].data=jsonData;
                            mapChart.setOption(mapoption,true);
                            $(window).resize(mapChart.resize);
                            charts.push(mapChart);
                       }
                   },
                   error:function(data){
                       parent.layer.alert('系统发生错误!', {icon: 5});
                   }
            });
        }
    这里需要注意地方是,echarts中的各省份名称是不太准确的,比如新疆维吾尔族自治区,湖南省,北京市等等。省级行政区域名称只取了前两位,而黑龙江和内蒙古则是取了前3位。这里采用的方式是采用前端数据构造的方法,将后端的数据按照echarts的规范来准换。因此在上述代码中,对于黑龙江等省份截取前3位。其它省份或者直辖市自治区采用截取前2位的方式。

2、次数排名统计

    次数排名统计,我们设计了两个柱状统计图,分别从次数最多和最少分别取前10进行数据展示。为了完整显示全国各省份的主要信息,我们也提供完整的数据表格清单。柱状统计图的关键代码如下:
provinceLineChart = echarts.init(document.getElementById("echarts-province-chart"));
minprovinceChart = echarts.init(document.getElementById("echarts-minprovince-chart"));
$(window).resize(provinceLineChart.resize);
$(window).resize(minprovinceChart.resize);
charts.push(provinceLineChart);
charts.push(minprovinceChart);
initProvinceChart();
    同样图表的数据初始化采用ajax的方式调用,关键代码如下:
function initProvinceChart(){
            $.ajax({
                   type: "POST",
                   url: ctx + "eq/province/echarts/provinceline",
                   data: {},
                   dataType : "json",
                   success: function(serverdata){
                       if(serverdata != ""){
                               var serverJsonData = eval('('+serverdata.maxdata+')');
                               provinceLineChart.setOption(serverJsonData,true);
                               $(window).resize(provinceLineChart.resize);
                               
                               var minData = eval('('+serverdata.mindata+')');
                               minprovinceChart.setOption(minData,true);
                               $(window).resize(minprovinceChart.resize);
                       }
                   },
                   error:function(data){
                       parent.layer.alert('系统发生错误!', {icon: 5});
                   }
            });
        }

三、最终结果展示

    经过前后端功能的设计和开发,在完成上述代码的开发之后,我们来看一下实际的效果。看看全国各省的地震震发情况究竟是怎么样的。

1、地图展示

    通过echarts图表可以很清楚的看到,在我国的西北和西南,地震的震发次数是非常多,地壳活动也是非常的活跃,新疆维吾尔族自治区,从次数来看一骑绝尘,新疆的地震次数还是非常多的(从公开数据来看)都变成红色的。 具体的数据可以使用鼠标悬浮到对应省份上会悬浮提示地震的次数,如下图所示:

2、图表展示

    图表展示将根据地震的震发次数,将次数最多的top10和最少的top10进行展示。方便大家对全国的相关数据有一个直观的掌握。首先来看一下地震次数最多的前10名是哪几个省份。

     地震次数最多的前10名依次是:新疆维吾尔自治区、四川省、西藏自治区、云南省、青海省、河北省、台湾省、内蒙古自治区、辽宁省。看完次数最多前10的,再来看安全系数最高的那几个省。

    按照次数分别是上海市、海南省、江西省、湖南省、福建省、天津市、北京市、河南省、山东省、江苏省。 其它没有进入统计图的省份具体次数如下:

总结

    以上就是本文的主要内容,本文主要面向对于Leaflet等gis可视化框架不熟悉的朋友,在不使用gis可视化框架的同时进行地图应用的开发。本文将重点讲解如何使用SpringBoot进行后端接口的开发,基于后端java语言,直接构造前端echarts图表展示需要的数据。文章的最后,我们会输出一个使用Echarts开发的全国各省地震震发情况统计图、全国地震次数排名前10名和倒数10名(相对安全)的省份以及完整的统计数据列表。行文仓促,难免有诸多不足之处,欢迎朋友们在评论区批评指正,万分感谢。

本文转载自: https://blog.csdn.net/yelangkingwuzuhu/article/details/136751845
版权归原作者 夜郎king 所有, 如有侵权,请联系我们删除。

“基于SpringBoot和Echarts的全国地震可视化分析实战”的评论:

还没有评论