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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章