02 【ArcGIS JS API + eCharts系列】實現二、三維遷徙圖的繪製

概述

上一篇文章通過純前端的方式實現了ArcGIS JS API和eCharts的普通二維圖表繪製,因爲這些圖表繪製其實是跟地理座標無關的,只需要設置圖表的位置即可,所以僅僅用了純前端的方式去實現。這篇文章通過參考【dGIS】大佬的文章,重構了EchartsLayer.js文件(因爲網上所有關於EchartsLayer.js文件的代碼全部是編譯過的,閱讀起來很不友好,並且有些EchartsLayer.js擴展文件僅僅支持到ArcGIS JS API 4.6版本,對於ArcGIS JS API 4.14這樣的高版本切換還是有一些問題),使其支持最新版的ArcGIS API for JavaScript 4.14和eCharts 4版本,實現了在ArcGIS的底圖上使其能夠繪製二維和三維的遷徙圖,我們先來看一下效果:

 

實現思路

遷徙圖、散點圖這種圖表跟地理座標關係緊密,所以僅僅通過二維普通圖表繪製的方式是無法實現這類圖表繪製的,所以就需要我們來擴展eCharts的相關功能,使其能夠夠結合最新版的ArcGIS JS API來完成地圖上這類圖表的繪製,eCharts官網也提供了相應的擴展插件,但這種插件並不能很好地支持我們ArcGIS JS API的高版本,所以我們在這篇文章裏直接擴展了一個圖層類,下面是具體的實現思路:

實現ArcGIS JS API和eCharts的結合,最最關鍵的是要實現兩個插件庫裏的座標系轉換,這是重點,只要搞清楚了這一點,我們完全可以脫離地圖API庫的束縛,理論上可以實現eCharts跟任意地圖庫的結合。在此處轉換座標時我們使用了eCharts提供的registerCoordinateSystem方法,通過這個方法我們註冊了一個名爲"arcgis"的座標系,裏面對eCharts中的dataToPoint、pointToData等方法進行了重寫,然後將這些所有內容封裝爲了一個EchartsLayer圖層類。至於這個文件的源碼,文章結尾會提供,接下來我們看一下具體的實現步驟。

 

實現步驟

1、本文所用的demo是基於React框架搭建的,所以我們首先基於React框架搭建一個初始化項目,然後改寫src目錄下的App.js這個主文件,實例化出一張二維地圖,這中間用到了esri-loader插件,具體的實現過程可查看我的這篇文章【【番外】 React中使用ArcGIS JS API 4.14開發】,裏面有具體的實現步驟。

2、通過上述操作實例化完一張二維地圖後,我們接下來就要進行遷徙圖的繪製操作了,在開始之前我們需要一些數據,首先是遷徙途中所要用到的各個行政區劃的省會城市座標,是一份JSON文件,源文件如下:

let GeoCodingData = {
    '海門': [121.15, 31.89],
    '鄂爾多斯': [109.781327, 39.608266],
    '招遠': [120.38, 37.35],
    '舟山': [122.207216, 29.985295],
    '齊齊哈爾': [123.97, 47.33],
    '鹽城': [120.13, 33.38],
    '赤峯': [118.87, 42.28],
    '青島': [120.33, 36.07],
    '乳山': [121.52, 36.89],
    '金昌': [102.188043, 38.520089],
    '泉州': [118.58, 24.93],
    '萊西': [120.53, 36.86],
    '日照': [119.46, 35.42],
    '膠南': [119.97, 35.88],
    '南通': [121.05, 32.08],
    '拉薩': [91.11, 29.97],
    '雲浮': [112.02, 22.93],
    '梅州': [116.1, 24.55],
    '文登': [122.05, 37.2],
    '上海': [121.48, 31.22],
    '攀枝花': [101.718637, 26.582347],
    '威海': [122.1, 37.5],
    '承德': [117.93, 40.97],
    '廈門': [118.1, 24.46],
    '汕尾': [115.375279, 22.786211],
    '潮州': [116.63, 23.68],
    '丹東': [124.37, 40.13],
    '太倉': [121.1, 31.45],
    '曲靖': [103.79, 25.51],
    '煙臺': [121.39, 37.52],
    '福州': [119.3, 26.08],
    '瓦房店': [121.979603, 39.627114],
    '即墨': [120.45, 36.38],
    '撫順': [123.97, 41.97],
    '玉溪': [102.52, 24.35],
    '張家口': [114.87, 40.82],
    '陽泉': [113.57, 37.85],
    '萊州': [119.942327, 37.177017],
    '湖州': [120.1, 30.86],
    '汕頭': [116.69, 23.39],
    '崑山': [120.95, 31.39],
    '寧波': [121.56, 29.86],
    '湛江': [110.359377, 21.270708],
    '揭陽': [116.35, 23.55],
    '榮成': [122.41, 37.16],
    '連雲港': [119.16, 34.59],
    '葫蘆島': [120.836932, 40.711052],
    '常熟': [120.74, 31.64],
    '東莞': [113.75, 23.04],
    '河源': [114.68, 23.73],
    '淮安': [119.15, 33.5],
    '泰州': [119.9, 32.49],
    '南寧': [108.33, 22.84],
    '營口': [122.18, 40.65],
    '惠州': [114.4, 23.09],
    '江陰': [120.26, 31.91],
    '蓬萊': [120.75, 37.8],
    '韶關': [113.62, 24.84],
    '嘉峪關': [98.289152, 39.77313],
    '廣州': [113.23, 23.16],
    '延安': [109.47, 36.6],
    '太原': [112.53, 37.87],
    '清遠': [113.01, 23.7],
    '中山': [113.38, 22.52],
    '昆明': [102.73, 25.04],
    '壽光': [118.73, 36.86],
    '盤錦': [122.070714, 41.119997],
    '長治': [113.08, 36.18],
    '深圳': [114.07, 22.62],
    '珠海': [113.52, 22.3],
    '宿遷': [118.3, 33.96],
    '咸陽': [108.72, 34.36],
    '銅川': [109.11, 35.09],
    '平度': [119.97, 36.77],
    '佛山': [113.11, 23.05],
    '海口': [110.35, 20.02],
    '江門': [113.06, 22.61],
    '章丘': [117.53, 36.72],
    '肇慶': [112.44, 23.05],
    '大連': [121.62, 38.92],
    '臨汾': [111.5, 36.08],
    '吳江': [120.63, 31.16],
    '石嘴山': [106.39, 39.04],
    '瀋陽': [123.38, 41.8],
    '蘇州': [120.62, 31.32],
    '茂名': [110.88, 21.68],
    '嘉興': [120.76, 30.77],
    '長春': [125.35, 43.88],
    '膠州': [120.03336, 36.264622],
    '銀川': [106.27, 38.47],
    '張家港': [120.555821, 31.875428],
    '三門峽': [111.19, 34.76],
    '錦州': [121.15, 41.13],
    '南昌': [115.89, 28.68],
    '柳州': [109.4, 24.33],
    '三亞': [109.511909, 18.252847],
    '自貢': [104.778442, 29.33903],
    '吉林': [126.57, 43.87],
    '陽江': [111.95, 21.85],
    '瀘州': [105.39, 28.91],
    '西寧': [101.74, 36.56],
    '宜賓': [104.56, 29.77],
    '呼和浩特': [111.65, 40.82],
    '成都': [104.06, 30.67],
    '大同': [113.3, 40.12],
    '鎮江': [119.44, 32.2],
    '桂林': [110.28, 25.29],
    '張家界': [110.479191, 29.117096],
    '宜興': [119.82, 31.36],
    '北海': [109.12, 21.49],
    '西安': [108.95, 34.27],
    '金壇': [119.56, 31.74],
    '東營': [118.49, 37.46],
    '牡丹江': [129.58, 44.6],
    '遵義': [106.9, 27.7],
    '紹興': [120.58, 30.01],
    '揚州': [119.42, 32.39],
    '常州': [119.95, 31.79],
    '濰坊': [119.1, 36.62],
    '重慶': [106.54, 29.59],
    '台州': [121.420757, 28.656386],
    '南京': [118.78, 32.04],
    '濱州': [118.03, 37.36],
    '貴陽': [106.71, 26.57],
    '無錫': [120.29, 31.59],
    '本溪': [123.73, 41.3],
    '克拉瑪依': [84.77, 45.59],
    '渭南': [109.5, 34.52],
    '馬鞍山': [118.48, 31.56],
    '寶雞': [107.15, 34.38],
    '焦作': [113.21, 35.24],
    '句容': [119.16, 31.95],
    '北京': [116.46, 39.92],
    '徐州': [117.2, 34.26],
    '衡水': [115.72, 37.72],
    '包頭': [110, 40.58],
    '綿陽': [104.73, 31.48],
    '烏魯木齊': [87.68, 43.77],
    '棗莊': [117.57, 34.86],
    '杭州': [120.19, 30.26],
    '淄博': [118.05, 36.78],
    '鞍山': [122.85, 41.12],
    '溧陽': [119.48, 31.43],
    '庫爾勒': [86.06, 41.68],
    '安陽': [114.35, 36.1],
    '開封': [114.35, 34.79],
    '濟南': [117, 36.65],
    '德陽': [104.37, 31.13],
    '溫州': [120.65, 28.01],
    '九江': [115.97, 29.71],
    '邯鄲': [114.47, 36.6],
    '臨安': [119.72, 30.23],
    '蘭州': [103.73, 36.03],
    '滄州': [116.83, 38.33],
    '臨沂': [118.35, 35.05],
    '南充': [106.110698, 30.837793],
    '天津': [117.2, 39.13],
    '富陽': [119.95, 30.07],
    '泰安': [117.13, 36.18],
    '諸暨': [120.23, 29.71],
    '鄭州': [113.65, 34.76],
    '哈爾濱': [126.63, 45.75],
    '聊城': [115.97, 36.45],
    '蕪湖': [118.38, 31.33],
    '唐山': [118.02, 39.63],
    '平頂山': [113.29, 33.75],
    '邢臺': [114.48, 37.05],
    '德州': [116.29, 37.45],
    '濟寧': [116.59, 35.38],
    '荊州': [112.239741, 30.335165],
    '宜昌': [111.3, 30.7],
    '義烏': [120.06, 29.32],
    '麗水': [119.92, 28.45],
    '洛陽': [112.44, 34.7],
    '秦皇島': [119.57, 39.95],
    '株洲': [113.16, 27.83],
    '石家莊': [114.48, 38.03],
    '萊蕪': [117.67, 36.19],
    '常德': [111.69, 29.05],
    '保定': [115.48, 38.85],
    '湘潭': [112.91, 27.87],
    '金華': [119.64, 29.12],
    '岳陽': [113.09, 29.37],
    '長沙': [113, 28.21],
    '衢州': [118.88, 28.97],
    '廊坊': [116.7, 39.53],
    '菏澤': [115.480656, 35.23375],
    '合肥': [117.27, 31.86],
    '武漢': [114.31, 30.52],
    '大慶': [125.03, 46.58]
};

export default GeoCodingData;

在此處因爲數據量有點大,所以我將它單獨提出來作爲一個文件,放在項目目錄的data文件夾下,然後需要在我們的組件中定義state,裏面存放一些遷徙圖各個中心點的數據和後期創建地圖後繪製圖表時所要用到的數據,如下:

    state = {
        BJData: [
            [{name:'北京'}, {name:'上海',value:95}],
            [{name:'北京'}, {name:'廣州',value:90}],
            [{name:'北京'}, {name:'大連',value:80}],
            [{name:'北京'}, {name:'南寧',value:70}],
            [{name:'北京'}, {name:'南昌',value:60}],
            [{name:'北京'}, {name:'拉薩',value:50}],
            [{name:'北京'}, {name:'長春',value:40}],
            [{name:'北京'}, {name:'包頭',value:30}],
            [{name:'北京'}, {name:'重慶',value:20}],
            [{name:'北京'}, {name:'常州',value:10}]
        ],
        SHData: [
            [{name:'上海'},{name:'包頭',value:95}],
            [{name:'上海'},{name:'昆明',value:90}],
            [{name:'上海'},{name:'廣州',value:80}],
            [{name:'上海'},{name:'鄭州',value:70}],
            [{name:'上海'},{name:'長春',value:60}],
            [{name:'上海'},{name:'重慶',value:50}],
            [{name:'上海'},{name:'長沙',value:40}],
            [{name:'上海'},{name:'北京',value:30}],
            [{name:'上海'},{name:'丹東',value:20}],
            [{name:'上海'},{name:'大連',value:10}]
        ],
        GZData: [
            [{name:'廣州'},{name:'福州',value:95}],
            [{name:'廣州'},{name:'太原',value:90}],
            [{name:'廣州'},{name:'長春',value:80}],
            [{name:'廣州'},{name:'重慶',value:70}],
            [{name:'廣州'},{name:'西安',value:60}],
            [{name:'廣州'},{name:'成都',value:50}],
            [{name:'廣州'},{name:'常州',value:40}],
            [{name:'廣州'},{name:'北京',value:30}],
            [{name:'廣州'},{name:'北海',value:20}],
            [{name:'廣州'},{name:'海口',value:10}]
        ],
        planePath: 'path://M1705.06,1318.313v-89.254l-319.9-221.799l0.073-208.063c0.521-84.662-26.629-121.796-63.961-121.491c-37.332-0.305-64.482,36.829-63.961,121.491l0.073,208.063l-319.9,221.799v89.254l330.343-157.288l12.238,241.308l-134.449,92.931l0.531,42.034l175.125-42.917l175.125,42.917l0.531-42.034l-134.449-92.931l12.238-241.308L1705.06,1318.313z',       //遷徙圖上的移動樣式,目前是默認的小飛機,後期可以自己改
        color: ['#F4EF8D', '#323296', '#CB4743'],      //各個遷徙中心點的航線顏色
        series: [],      //eCharts繪製時所需的配置信息
        mapview: null,   //實例化地圖後存放地圖視圖

2、定義完上述的基礎數據之後,我們接下來進行遷徙圖的繪製,這中間其實就是配置一些繪製遷徙圖時所要用到的eCharts圖表的配置信息,我們將這些配置信息全部壓到state中的series數組中去,代碼如下:

    _initCharts=() => {
        const _self = this;
        let placeCenter = [
            ['北京', this.state.BJData], 
            ['上海', this.state.SHData], 
            ['廣州', this.state.GZData]
        ];

        placeCenter.map((value, key) => {
            _self.state.series.push({
                name: value[0] + 'Top10',
                type: 'lines',
                coordinateSystem: 'arcgis',
                zlevel: 1,
                effect: {
                    show: true,
                    period: 6,
                    trailLength: 0.7,
                    color: '#fff',
                    symbolSize: 3
                },
                lineStyle: {
                    normal: {
                        color: _self.state.color[key],
                        width: 0,
                        curveness: 0.2
                    }
                },
                data: _self._convertData(value[1])
            }, {
                name: value[0] + ' Top10',
                type: 'lines',
                coordinateSystem: 'arcgis',
                zlevel: 2,
                symbol: ['none', 'arrow'],
                symbolSize: 10,
                effect: {
                    show: true,
                    period: 6,
                    trailLength: 0,
                    symbol: _self.state.planePath,
                    symbolSize: 15
                },
                lineStyle: {
                  normal: {
                    color: _self.state.color[key],
                    width: 1,
                    opacity: 0.6,
                    curveness: 0.2
                  }
                },
                data: _self._convertData(value[1])
            }, {
                name: value[0] + ' Top10',
                type: 'effectScatter',
                coordinateSystem: 'arcgis',
                zlevel: 2,
                rippleEffect: {
                    brushType: 'stroke'
                },
                label: {
                    normal: {
                        show: true,
                        position: 'left',
                        formatter: '{b}'
                    }
                },
                symbolSize: function (val) {
                    return val[2] / 8;
                },
                itemStyle: {
                    normal: {
                        color: _self.state.color[key]
                    }
                },
                data: value[1].map(function(dataItem) {
                    return {
                        name: dataItem[1].name,
                        value: GeoCodingData[dataItem[1].name].concat([dataItem[1].value])
                    };
                })
            });
        });
    }

上面過程中用到了_convertData方法,主要用於數據的轉換,代碼如下:

    _convertData=(data) => {
        let res = [];
            for (var i = 0; i < data.length; i++) {
              var dataItem = data[i];
              var fromCoord = GeoCodingData[dataItem[0].name];
              var toCoord = GeoCodingData[dataItem[1].name];
              if (fromCoord && toCoord) {
                res.push({
                  fromName: dataItem[0].name,
                  toName: dataItem[1].name,
                  coords: [fromCoord, toCoord],
                  value: dataItem[1].value
                });
              }
            }
        return res;
    }

3、經過上述的操作,我們已經完成了底圖的繪製和遷徙圖的配置信息實例化,接下來就進行遷徙圖的繪製操作。繪製過程要監聽底圖實例化的when方法,等待地圖實例化完成之後再進行繪製,代碼如下:

view.when(function() {
	_self.state.mapview = view;
	_self._drawCharts();
});
    _drawCharts=() => {
        const _self = this;
        const options = {
            url: 'https://js.arcgis.com/4.14/dojo/dojo.js',
        };

        loadModules([
            'http://localhost/test/EchartsLayer.min.js'
        ], options).then(([
            echartsLayer
        ]) => {
            console.log(_self.state.mapview)
            //_self.state.mapview.when(function(){
                let chart = new echartsLayer(_self.state.mapview);
                let option = {
                    title: {
                        text: 'ArcGIS API for Javascript4.14擴展Echarts4之模擬遷徙',
                        subtext: 'Develop By X北辰北',
                        left: 'center',
                        textStyle: {
                            color: '#fff'
                        }
                    },
                    series: _self.state.series
                };
                chart.setChartOption(option);
            //});
        }
        ).catch((err) => {
            console.log('圖表繪製失敗,' + err);
        });
    }

4、經過以上操作後我們就完成了遷徙圖的繪製,在這裏要注意的是,繪製遷徙圖時要調用我們擴展的EchartsLayer圖層類,這個圖層類我們只需要將它放到本級服務器目錄下即可,或者放在demo的項目文件夾下面,然後我們引入dojo文件的時候不用上述代碼裏的那樣引用官網的dojo文件,而是自己下載dojo文件到demo項目裏,然後在引入EchartsLayer圖層類之前通過dojoConfig類配置下引用路徑就好了。

5、以上過程完成了二維場景下遷徙圖的繪製,三維場景下的繪製其實很簡單,我們只需要將視圖層換成三維就可以了,代碼如下:、

let view = new SceneView({
	container: "mapview", 
	map: map, 
	scale: 50000000, 
	center: [107.246152,34.414465] 
});

6、以上就是遷徙圖在二維和三維下的繪製過程。

 

總結

本文主要介紹下ArcGIS JS API高版本和eCharts 4版本的結合使用,在這篇文章裏最重要的是我們實現了兩個圖表庫中的座標系轉換工作,只要完成了這個步驟,那接下來的繪製其實跟eCharts的普通繪製是相差不大的,後期我會繼續更新EchartsLayer這個圖層類,迎合最新版的ArcGIS JS API,歡迎大家持續關注。

 

附:

App.js全部代碼

import React,{Component} from 'react';
import { loadModules } from 'esri-loader';
import GeoCodingData from './data/geoCodingData';
import './App.css';

class App extends Component {

    state = {
        BJData: [
            [{name:'北京'}, {name:'上海',value:95}],
            [{name:'北京'}, {name:'廣州',value:90}],
            [{name:'北京'}, {name:'大連',value:80}],
            [{name:'北京'}, {name:'南寧',value:70}],
            [{name:'北京'}, {name:'南昌',value:60}],
            [{name:'北京'}, {name:'拉薩',value:50}],
            [{name:'北京'}, {name:'長春',value:40}],
            [{name:'北京'}, {name:'包頭',value:30}],
            [{name:'北京'}, {name:'重慶',value:20}],
            [{name:'北京'}, {name:'常州',value:10}]
        ],
        SHData: [
            [{name:'上海'},{name:'包頭',value:95}],
            [{name:'上海'},{name:'昆明',value:90}],
            [{name:'上海'},{name:'廣州',value:80}],
            [{name:'上海'},{name:'鄭州',value:70}],
            [{name:'上海'},{name:'長春',value:60}],
            [{name:'上海'},{name:'重慶',value:50}],
            [{name:'上海'},{name:'長沙',value:40}],
            [{name:'上海'},{name:'北京',value:30}],
            [{name:'上海'},{name:'丹東',value:20}],
            [{name:'上海'},{name:'大連',value:10}]
        ],
        GZData: [
            [{name:'廣州'},{name:'福州',value:95}],
            [{name:'廣州'},{name:'太原',value:90}],
            [{name:'廣州'},{name:'長春',value:80}],
            [{name:'廣州'},{name:'重慶',value:70}],
            [{name:'廣州'},{name:'西安',value:60}],
            [{name:'廣州'},{name:'成都',value:50}],
            [{name:'廣州'},{name:'常州',value:40}],
            [{name:'廣州'},{name:'北京',value:30}],
            [{name:'廣州'},{name:'北海',value:20}],
            [{name:'廣州'},{name:'海口',value:10}]
        ],
        planePath: 'path://M1705.06,1318.313v-89.254l-319.9-221.799l0.073-208.063c0.521-84.662-26.629-121.796-63.961-121.491c-37.332-0.305-64.482,36.829-63.961,121.491l0.073,208.063l-319.9,221.799v89.254l330.343-157.288l12.238,241.308l-134.449,92.931l0.531,42.034l175.125-42.917l175.125,42.917l0.531-42.034l-134.449-92.931l12.238-241.308L1705.06,1318.313z',
        color: ['#F4EF8D', '#323296', '#CB4743'],
        series: [],
        mapview: null,
    };

    componentDidMount=() => {
        this._createMapview();
        this._initCharts();
    }

    //創建二維地圖
    _createMapview=() => {
        const _self = this;
        const options = {
            url: 'https://js.arcgis.com/4.14/',
            css: 'https://js.arcgis.com/4.14/esri/themes/light/main.css'
        };

        loadModules(['esri/Map',
            'esri/Basemap',
            'esri/layers/TileLayer',
            'esri/views/MapView',
            'esri/views/SceneView',
        ], options).then(([
            Map, 
            Basemap,
            TileLayer,
            MapView,
            SceneView,
        ]) => {
                    let basemap = new Basemap({
                        baseLayers: [
                            new TileLayer({
                                url: "http://map.geoq.cn/arcgis/rest/services/ChinaOnlineStreetPurplishBlue/MapServer",
                                title: "Basemap"
                            })
                        ],
                        title: "basemap",
                        id: "basemap"
                    });
                    let map = new Map({
                        basemap: basemap
                    });
                    // let view = new MapView({
                    //     container: "mapview", 
                    //     map: map, 
                    //     zoom: 5, 
                    //     center: [107.246152,34.414465] 
                    // });
                    let view = new SceneView({
                        container: "mapview", 
                        map: map, 
                        scale: 50000000, 
                        center: [107.246152,34.414465] 
                    });
                    
                    view.when(function() {
                        _self.state.mapview = view;
                        _self._drawCharts();
                    });
            }
        ).catch((err) => {
            console.log('底圖創建失敗,' + err);
        });
    }

    _initCharts=() => {
        const _self = this;
        let placeCenter = [
            ['北京', this.state.BJData], 
            ['上海', this.state.SHData], 
            ['廣州', this.state.GZData]
        ];

        placeCenter.map((value, key) => {
            _self.state.series.push({
                name: value[0] + 'Top10',
                type: 'lines',
                coordinateSystem: 'arcgis',
                zlevel: 1,
                effect: {
                    show: true,
                    period: 6,
                    trailLength: 0.7,
                    color: '#fff',
                    symbolSize: 3
                },
                lineStyle: {
                    normal: {
                        color: _self.state.color[key],
                        width: 0,
                        curveness: 0.2
                    }
                },
                data: _self._convertData(value[1])
            }, {
                name: value[0] + ' Top10',
                type: 'lines',
                coordinateSystem: 'arcgis',
                zlevel: 2,
                symbol: ['none', 'arrow'],
                symbolSize: 10,
                effect: {
                    show: true,
                    period: 6,
                    trailLength: 0,
                    symbol: _self.state.planePath,
                    symbolSize: 15
                },
                lineStyle: {
                  normal: {
                    color: _self.state.color[key],
                    width: 1,
                    opacity: 0.6,
                    curveness: 0.2
                  }
                },
                data: _self._convertData(value[1])
            }, {
                name: value[0] + ' Top10',
                type: 'effectScatter',
                coordinateSystem: 'arcgis',
                zlevel: 2,
                rippleEffect: {
                    brushType: 'stroke'
                },
                label: {
                    normal: {
                        show: true,
                        position: 'left',
                        formatter: '{b}'
                    }
                },
                symbolSize: function (val) {
                    return val[2] / 8;
                },
                itemStyle: {
                    normal: {
                        color: _self.state.color[key]
                    }
                },
                data: value[1].map(function(dataItem) {
                    return {
                        name: dataItem[1].name,
                        value: GeoCodingData[dataItem[1].name].concat([dataItem[1].value])
                    };
                })
            });
        });
    }

    _convertData=(data) => {
        let res = [];
            for (var i = 0; i < data.length; i++) {
              var dataItem = data[i];
              var fromCoord = GeoCodingData[dataItem[0].name];
              var toCoord = GeoCodingData[dataItem[1].name];
              if (fromCoord && toCoord) {
                res.push({
                  fromName: dataItem[0].name,
                  toName: dataItem[1].name,
                  coords: [fromCoord, toCoord],
                  value: dataItem[1].value
                });
              }
            }
        return res;
    }

    _drawCharts=() => {
        const _self = this;
        const options = {
            url: 'https://js.arcgis.com/4.14/dojo/dojo.js',
        };

        loadModules([
            'http://localhost/test/EchartsLayer.min.js'
        ], options).then(([
            echartsLayer
        ]) => {
            console.log(_self.state.mapview)
            //_self.state.mapview.when(function(){
                let chart = new echartsLayer(_self.state.mapview);
                let option = {
                    title: {
                        text: 'ArcGIS API for Javascript4.14擴展Echarts4之模擬遷徙',
                        subtext: 'Develop By X北辰北',
                        left: 'center',
                        textStyle: {
                            color: '#fff'
                        }
                    },
                    series: _self.state.series
                };
                chart.setChartOption(option);
            //});
        }
        ).catch((err) => {
            console.log('底圖創建失敗,' + err);
        });
    }

    render() {
        return (
            <div className="mainview">
                <div id="mapview"></div>
            </div>
          );
    }
}

export default App;

EchartsLayer.min.js全部代碼

var _0x4564=['prototype','setMapOffset','dataToPoint','point','toScreen','pointToData','toMap','getViewRect','BoundingRect','getRoamTransform','dojo/_base/declare','dojo/_base/lang','esri/geometry/Point','esri/geometry/SpatialReference','EchartsglLayer','registerCoordinateSystem','arcgis','getE3CoordinateSystem','init','setBaseMap','createLayer','view','chartOption','setCharts','box','visible','hidden','chart','off','undefined','extent','xAxis','xmin','xmax','yAxis','ymin','ymax','setOption','animation','createElement','div','setAttribute','echartsData','name','style','width','height','position','absolute','top','left','getElementsByClassName','esri-view-surface','appendChild','startMapEventListeners','outerHTML','originLyr','features','screenData','map_DragStart_Listener','remove','map_DragEnd_Listener','map_ZoomStart_Listener','map_ZoomEnd_Listener','map_ExtentChange_Listener','watch','hitch','resize','rotation','map','_mapOffset','create','eachSeries','get','coordinateSystem','getDimensionsInfo','dimensions'];(function(_0x4ea369,_0x173297){var _0x432a1a=function(_0x3b4d7a){while(--_0x3b4d7a){_0x4ea369['push'](_0x4ea369['shift']());}};_0x432a1a(++_0x173297);}(_0x4564,0xf1));var _0x1824=function(_0x20e690,_0x5f0396){_0x20e690=_0x20e690-0x0;var _0x841fe2=_0x4564[_0x20e690];return _0x841fe2;};define([_0x1824('0x0'),_0x1824('0x1'),_0x1824('0x2'),_0x1824('0x3')],function(_0x4156fb,_0x59c3eb,_0x275378,_0x4d54b1){return _0x4156fb(_0x1824('0x4'),null,{'name':_0x1824('0x4'),'view':null,'box':null,'chart':null,'chartOption':null,'visible':!![],'constructor':function(_0x27b7d3,_0x649a95){echarts[_0x1824('0x5')](_0x1824('0x6'),this[_0x1824('0x7')](_0x27b7d3));this[_0x1824('0x8')](_0x27b7d3,_0x649a95);},'init':function(_0x3a80a9,_0x5617d3){this[_0x1824('0x9')](_0x3a80a9);this[_0x1824('0xa')]();},'setBaseMap':function(_0x3ddf37){this[_0x1824('0xb')]=_0x3ddf37;},'setChartOption':function(_0x497153){this[_0x1824('0xc')]=_0x497153;this[_0x1824('0xd')]();},'setVisible':function(_0x36aa18){if(!this[_0x1824('0xe')]||this[_0x1824('0xf')]===_0x36aa18)return;this[_0x1824('0xe')][_0x1824('0x10')]=!_0x36aa18;this[_0x1824('0xf')]=_0x36aa18;_0x36aa18===!![]&&setCharts();},'refreshBegin':function(){this[_0x1824('0xe')][_0x1824('0x10')]=!![];},'refreshing':function(){setCharts();},'refreshEnd':function(){this[_0x1824('0xe')][_0x1824('0x10')]=![];},'on':function(_0x5dd691,_0x472109,_0x4b90b9){this[_0x1824('0x11')]['on'](_0x5dd691,_0x472109,_0x4b90b9);},'off':function(_0x25e82f,_0x44fdf2,_0x3cd39d){this[_0x1824('0x11')][_0x1824('0x12')](_0x25e82f,_0x44fdf2,_0x3cd39d);},'map_DragStart_Listener':null,'map_DragEnd_Listener':null,'map_ZoomStart_Listener':null,'map_ZoomEnd_Listener':null,'map_ExtentChange_Listener':null,'map_click_Listener':null,'setCharts':function(){if(!this[_0x1824('0xf')])return;if(this[_0x1824('0xc')]==null||this[_0x1824('0xc')]==_0x1824('0x13'))return;let _0x50f53f=this[_0x1824('0xb')][_0x1824('0x14')];this[_0x1824('0xc')][_0x1824('0x15')]={'show':![],'min':_0x50f53f[_0x1824('0x16')],'max':_0x50f53f[_0x1824('0x17')]};this[_0x1824('0xc')][_0x1824('0x18')]={'show':![],'min':_0x50f53f[_0x1824('0x19')],'max':_0x50f53f[_0x1824('0x1a')]};this[_0x1824('0x11')][_0x1824('0x1b')](this[_0x1824('0xc')]);this[_0x1824('0xc')][_0x1824('0x1c')]=![];},'createLayer':function(){let _0x56973d=this[_0x1824('0xe')]=document[_0x1824('0x1d')](_0x1824('0x1e'));_0x56973d[_0x1824('0x1f')]('id',_0x1824('0x20'));_0x56973d[_0x1824('0x1f')](_0x1824('0x21'),_0x1824('0x20'));_0x56973d[_0x1824('0x22')][_0x1824('0x23')]=this[_0x1824('0xb')][_0x1824('0x23')]+'px';_0x56973d[_0x1824('0x22')][_0x1824('0x24')]=this[_0x1824('0xb')][_0x1824('0x24')]+'px';_0x56973d[_0x1824('0x22')][_0x1824('0x25')]=_0x1824('0x26');_0x56973d[_0x1824('0x22')][_0x1824('0x27')]=0x0;_0x56973d[_0x1824('0x22')][_0x1824('0x28')]=0x0;let _0x22f992=document[_0x1824('0x29')](_0x1824('0x2a'))[0x0];_0x22f992[_0x1824('0x2b')](_0x56973d);this[_0x1824('0x11')]=echarts[_0x1824('0x8')](_0x56973d);this[_0x1824('0x2c')]();},'removeLayer':function(){this[_0x1824('0xe')][_0x1824('0x2d')]='';this[_0x1824('0xb')]=null;this[_0x1824('0xe')]=null;this[_0x1824('0x2e')]=null;this[_0x1824('0x2f')]=null;this[_0x1824('0x30')]=[];this[_0x1824('0x11')]=null;this[_0x1824('0xc')]=null;this[_0x1824('0x31')][_0x1824('0x32')]();this[_0x1824('0x33')][_0x1824('0x32')]();this[_0x1824('0x34')][_0x1824('0x32')]();this[_0x1824('0x35')][_0x1824('0x32')]();this[_0x1824('0x36')][_0x1824('0x32')]();},'startMapEventListeners':function(){let _0x576d14=this[_0x1824('0xb')];_0x576d14[_0x1824('0x37')](_0x1824('0x14'),_0x59c3eb[_0x1824('0x38')](this,function(){if(!this[_0x1824('0xf')])return;this[_0x1824('0xd')]();this[_0x1824('0x11')][_0x1824('0x39')]();this[_0x1824('0xe')][_0x1824('0x10')]=![];}));_0x576d14[_0x1824('0x37')](_0x1824('0x3a'),_0x59c3eb[_0x1824('0x38')](this,function(){if(!this[_0x1824('0xf')])return;this[_0x1824('0xd')]();this[_0x1824('0x11')][_0x1824('0x39')]();this[_0x1824('0xe')][_0x1824('0x10')]=![];}));},'getE3CoordinateSystem':function(_0x56f41a){var _0x4504c9=function _0x4504c9(_0x180267){this[_0x1824('0x3b')]=_0x180267;this[_0x1824('0x3c')]=[0x0,0x0];};_0x4504c9[_0x1824('0x3d')]=function(_0x1a4547){_0x1a4547[_0x1824('0x3e')](function(_0x17e9bb){if(_0x17e9bb[_0x1824('0x3f')](_0x1824('0x40'))===_0x1824('0x6')){_0x17e9bb[_0x1824('0x40')]=new _0x4504c9(_0x56f41a);}});};_0x4504c9[_0x1824('0x41')]=function(){return['x','y'];};_0x4504c9[_0x1824('0x42')]=['x','y'];_0x4504c9[_0x1824('0x43')][_0x1824('0x42')]=['x','y'];_0x4504c9[_0x1824('0x43')][_0x1824('0x44')]=function setMapOffset(_0xeffdb8){this[_0x1824('0x3c')]=_0xeffdb8;};_0x4504c9[_0x1824('0x43')][_0x1824('0x45')]=function dataToPoint(_0x209327){var _0x2755d4={'type':_0x1824('0x46'),'x':_0x209327[0x0],'y':_0x209327[0x1],'spatialReference':new _0x4d54b1(0x10e6)};var _0x3676a6=_0x56f41a[_0x1824('0x47')](_0x2755d4);var _0x52b765=this[_0x1824('0x3c')];return[_0x3676a6['x']-_0x52b765[0x0],_0x3676a6['y']-_0x52b765[0x1]];};_0x4504c9[_0x1824('0x43')][_0x1824('0x48')]=function pointToData(_0x5d9368){var _0x4282c5=this[_0x1824('0x3c')];var _0x3a367d={'x':_0x5d9368[0x0]+_0x4282c5[0x0],'y':_0x5d9368[0x1]+_0x4282c5[0x1]};var _0x3a9399=_0x56f41a[_0x1824('0x49')](_0x3a367d);return[_0x3a9399['x'],_0x3a9399['y']];};_0x4504c9[_0x1824('0x43')][_0x1824('0x4a')]=function getViewRect(){return new graphic[(_0x1824('0x4b'))](0x0,0x0,this[_0x1824('0x3b')][_0x1824('0x23')],this[_0x1824('0x3b')][_0x1824('0x24')]);};_0x4504c9[_0x1824('0x43')][_0x1824('0x4c')]=function getRoamTransform(){return matrix[_0x1824('0x3d')]();};return _0x4504c9;}});});

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章