QT 之ECharts加载shp方法

一 前言

在项目中图表的显示,ECharts的应用十分广泛,ECharts拥有非常丰富的图表库,可以绘制出各种各样漂亮的图表;最近在项目中需要用到对某个市进行分层设色来表示不同地区的某个值的分布情况。

https://www.echartsjs.com/examples/zh/index.html

ECharts提供了地图加载功能,可以使用百度API,也可使用离线的China.js 来加载地图;但是百度API只能在线使用,因为我们是本机单机使用,不能联网,所以只能采用离线的方式;离线的地图ECharts的 GIHUB上面有各省的地图,但是不够精细。

官方在线分层:https://www.echartsjs.com/examples/zh/editor.html?c=map-HK

官方离线分层:https://www.echartsjs.com/examples/zh/editor.html?c=map-usa

所以我在想,我自己有比较精细的shp图层数据,那能不能将它加载到ECharts上去呢,通过在某度上一翻查找,很快的找到了解决方法,接下来我来介绍一下我的解决方法。

二 效果图

三 方法

参考的博客:https://blog.csdn.net/rihongliu/article/details/78400353

依据网上的方法步骤如下:

1)准备需要加载的shp文件(包括图层的数据文件)

2)数据编辑整理

a)使用arcmap打开shp文件

b)编辑“属性表”,必要的属性有:name、cp、childNum、polygon,如果属性表中没有这些字段,用户可以手动在属性表中添加这些字段。然后保存。

注意:

在这里cp字段为多边形中心点,计算中心点的方式为,先新建两个double型字段:x,y,然后使用“计算几何...”分别计算出它们质心的x和y。然后再新建一个字符串字段,使用“字段计算器”公式("[" & [x] & "," & [y] & "]")将x,y字段合成一个数组字段。

c)将shp文件转换成geojson文件

这里我们可以使用一个在线的转换工具:http://mapshaper.org/

3)echarts本地加载".json"文件

利用jquery获取数据源,需要引用jquery库

<!DOCTYPE html>
<head>
    <meta charset="utf-8">
    <title>ECharts</title>
</head>
<body>
<!-- 为ECharts准备一个具备大小(宽高)的Dom -->
<div id="map" style="height:600px"></div>
<!-- ECharts单文件引入 -->
<script src="echarts.js"></script>
<script src="jquery.min.js"></script>
<script src="jquery.json.js"></script>
<script>
    $.getJSON("data/xiamen.json",function(data){
    echarts.registerMap('xiamen', data);   
    //定义div#map,给定width和height
    chart = echarts.init(document.getElementById('map'));
    chart.setOption({
	series: [{
                name: 'xiamen',
                type: 'map',
                map: 'xiamen',
            }]
	});
	})
</script>

</body>

4)使用chrom运行.html文件,我们会发出它不能加载,会出现跨域问题

解决办法:

方法一:问题本身问题在jquery,jquery在请求本地的.json的时候要跨域,所在我们需要搭建一个服务器然后再从服务器中加载,主要是从通过Apache来搭建,可以通过phpstudy来搭建一个服务器将网创建的html放入服务器目录,

 

 然后通过引用服务器地址,可以顺利加载,通过服务器地址打开效果如下:

方法二:虽然通过上面的搭建服务器的方式解决了这个问题,但始终觉得这个方法太复杂,始终觉得这个方法不是唯一的解决的方法,一定有什么方法可以不用搭建服务器就可以加载.json的方法。然后通过一翻查找,然后找到了解决方案,即采用jsonp的方式。

参考博客:https://blog.csdn.net/guolinghang/article/details/90229822

方法很简单,就是将.json文件的内容通过一个方法包起来,然后保存为js文件。

callData(
{"type":"FeatureCollection", "features": [
{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[117.99191310524449,24.550179203070382],[118.00478210500178,24.548154247192866]]]}}]}
)

然后在html加载

<!DOCTYPE html>
<head>
    <meta charset="utf-8">
    <title>ECharts</title>
</head>
<body>
<!-- 为ECharts准备一个具备大小(宽高)的Dom -->
<div id="map" style="height:600px"></div>
<!-- ECharts单文件引入 -->
<script src="echarts.js"></script>
<script>
    var chart;
    var callData=function(data){
    echarts.registerMap('xiamen', data);
    //定义div#map,给定width和height
    chart = echarts.init(document.getElementById('map'));
    option = {
           title: {
               text: '网络舆情传播动态',
               left: 'center'
           },
           tooltip: {
               trigger: 'item',
               showDelay: 0,
               transitionDuration: 0.2,
               formatter: function (params) {
                   var value = (params.value + '').split('.');
                   value = value[0].replace(/(\d{1,3})(?=(?:\d{3})+(?!\d))/g, '$1,');
                   return params.seriesName + '<br/>' + params.name + ': ' + value;
               }
           },
           visualMap: {
               left: 'right',
               min: 0,
               max: 10,
               inRange: {
                   color: ['#313695', '#4575b4', '#74add1', '#abd9e9', '#e0f3f8', '#ffffbf', '#fee090', '#fdae61', '#f46d43', '#d73027', '#a50026']
               },
               text:['High','Low'],           // 文本,默认为数值文本
               calculable: true
           },
           toolbox: {
               show: false,
               //orient: 'vertical',
               left: 'left',
               top: 'top',
               feature: {
                   dataView: {readOnly: false},
                   restore: {},
                   saveAsImage: {}
               }
           },
           series: [
                       {
                           aspectScale:1,    //不会产生形变
                           name: 'xiamen',
                           type: 'map',
                           roam: true,
                           map: 'xiamen',
                           itemStyle:{
                               emphasis:{label:{show:true}}
                           },
                           // 文本位置修正
                           textFixed: {
                               Alaska: [20, -20]
                           },
                           data:[]
                       }

           ]
       };

    chart.setOption(option);
    }
    </script>
    <!-- 载入数据,也可视为调用函数callData -->
    <script type="text/javascript" src="build/dist/xiamen.js"></script>
</script>

<script>
    function resizeWindow() {
        window.onresize = function () {
            chart.resize();
        }
    }

    resizeWindow();
</script>

</body>

 5)QT调用

a)搭建服务器方法调用

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->widget->load(QUrl("http://localhost:81/KDStatisticalChart2.html"));

}

b)改写成js方法的调用

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->widget->load(QUrl("E:/workspace/QT_PRJ/echartsTest/htmlEcharts/KDStatisticalChart2.html"));

}

c)数据加载

在html代码中添加JS代码

function updateMapData(datas) {
        //更新数据
        var option = chart.getOption();
        option.series[0].data = datas;
        chart.clear();
        chart.setOption(option);
    }

 cpp中添加

void MainWindow::on_test_map_clicked()
{
    QString datastr = "[{name: '厦港街道', value: 7},\
    {name: '中华街道', value: 8},\
    {name: '中华街道', value: 3},\
    {name: '滨海街道', value: 4},\
    {name: '鹭江街道', value: 5},\
    {name: '开元街道', value: 6},\
    {name: '梧村街道', value: 7},\
    {name: '筼筜街道', value: 8},\
    {name: '莲前街道', value: 9},\
    {name: '嘉莲街道', value: 4},\
    {name: '鼓浪屿街道', value: 9},\
    {name: '海沧街道', value: 8},\
    {name: '新阳街道', value: 7},\
    {name: '东孚镇', value: 6},\
    {name: '第一农场', value: 5},\
    {name: '海沧农场', value: 4},\
    {name: '天竺山林场', value: 3},\
    {name: '湖里街道', value: 2},\
    {name: '殿前街道', value: 1},\
    {name: '禾山街道', value: 2},\
    {name: '江头街道', value: 3},\
    {name: '金山街道', value: 2},\
    {name: '集美街道', value: 4},\
    {name: '侨英街道', value: 2},\
    {name: '杏林街道', value: 8},\
    {name: '杏滨街道', value: 10},\
    {name: '灌口镇', value: 6},\
    {name: '后溪镇', value: 2},\
    {name: '第二农场', value: 1},\
    {name: '天马华侨农场', value: 7},\
    {name: '阪头防护林场', value: 4},\
    {name: '大同街道', value: 3},\
    {name: '祥平街道', value: 4},\
    {name: '莲花镇', value: 8},\
    {name: '新民镇', value: 10},\
    {name: '洪塘镇', value: 6},\
    {name: '西柯镇', value: 5},\
    {name: '汀溪镇', value: 1},\
    {name: '五显镇', value: 2},\
    {name: '白沙仑农场', value: 3},\
    {name: '竹坝华侨农场', value: 4},\
    {name: '大嶝街道', value: 5},\
    {name: '马巷镇', value: 6},\
    {name: '新圩镇', value: 7},\
    {name: '新店镇', value: 8},\
    {name: '内厝镇', value: 9},\
    {name: '大帽山农场', value: 10}]";

    QString js = QString("updateMapData(%1)").arg(datastr);
    ui->widget->page()->runJavaScript(js);


}

四 结束语

感谢那些无私分享的人,给了我很大的帮助,以上是我的经验分享,也希望能够帮助到需要的人,如有疑问可以一起交流。

发布了55 篇原创文章 · 获赞 26 · 访问量 9万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章