前面兩篇文章經過擴展EchartsLayer.js這個圖層類,實現了使用ArcGIS JS API和eCharts,在二維和三維場景下繪製遷徙圖和散點圖。這篇文章繼續經過繪製網絡路徑圖的例子,再來驗證下咱們擴展的這個圖層類是否可用,先來看下最終效果:
css
遷徙圖、散點圖和網絡路徑圖這種圖表跟地理座標關係緊密,因此僅僅經過第一篇二維普通圖表繪製的方式是沒法實現這類圖表繪製的,因此就須要咱們來擴展eCharts的相關功能,使其可以夠結合最新版的ArcGIS JS API來完成地圖上這類圖表的繪製,eCharts官網也提供了相應的擴展插件,但這種插件並不能很好地支持咱們ArcGIS JS API的高版本,因此咱們在這篇文章裏直接擴展了一個圖層類,下面是具體的實現思路:
實現ArcGIS JS API和eCharts的結合,最最關鍵的是要實現兩個插件庫裏的座標系轉換,這是重點,只要搞清楚了這一點,咱們徹底能夠脫離地圖API庫的束縛,理論上能夠實現eCharts跟任意地圖庫的結合。在此處轉換座標時咱們使用了eCharts提供的registerCoordinateSystem方法,經過這個方法咱們註冊了一個名爲"arcgis"的座標系,裏面對eCharts中的dataToPoint、pointToData等方法進行了重寫,而後將這些全部內容封裝爲了一個EchartsLayer圖層類。至於這個文件的源碼,文章結尾會提供,接下來咱們看一下具體的實現步驟。前端
一、本文所用的demo一樣是基於React框架搭建的,因此咱們首先基於React框架搭建一個初始化項目,而後改寫src目錄下的App.js這個主文件,實例化出一張二維地圖,這中間用到了esri-loader插件,具體的實現過程可查看個人這篇文章【【番外】 React中使用ArcGIS JS API 4.14開發】,裏面有具體的實現步驟。
二、經過上述操做實例化完一張二維地圖後,咱們接下來就要進行網絡路徑圖的繪製操做了,在開始以前咱們須要數據,就是關於網絡路徑的座標數據和相應權重值的數據,我將它存在了一份JS文件裏,此文件比較大,因此並不打算在此處粘貼出來,有須要的能夠到此地址下載。
三、下載到數據後,將數據拷貝至demo代碼目錄下,而後在組件代碼中引入,此處咱們是將它引入到咱們新建的TrafficNetwork組件目錄下,而後編寫數據處理的函數,對下載下來的數據進行初始化處理,代碼以下:react
//初始化數據 _initData=() => { const _self = this; let data = trafficData; let hStep = 300 / (data.length - 1); _self.state.busLines = [].concat.apply([], data.map(function (busLine, idx) { let prevPt; let points = []; for (let i = 0; i < busLine.length; i += 2) { let pt = [busLine[i], busLine[i + 1]]; if (i > 0) { pt = [ prevPt[0] + pt[0], prevPt[1] + pt[1] ]; } prevPt = pt; points.push([pt[0] / 1e4, pt[1] / 1e4]); } return { coords: points, lineStyle: { normal: { color: echarts.color.modifyHSL('#5A94DF', Math.round(hStep * idx)) } } } })) }
四、數據初始完成後,咱們進行網絡路徑圖表的繪製信息配置,也就是初始化series屬性,代碼以下:網絡
//初始化圖表配置 _initCharts=() => { const _self = this; _self.state.series = [{ type: 'lines', coordinateSystem: 'arcgis', polyline: true, data: _self.state.busLines, silent: true, lineStyle: { // color: '#c23531', // color: 'rgb(200, 35, 45)', opacity: 0.2, width: 1 }, progressiveThreshold: 500, progressive: 200 }, { type: 'lines', coordinateSystem: 'arcgis', polyline: true, data: _self.state.busLines, lineStyle: { width: 0 }, effect: { constantSpeed: 20, show: true, trailLength: 0.1, symbolSize: 1.5 }, zlevel: 1 }] }
五、接下來和以前文章的流程同樣,監聽地圖的繪製完成事件,而後調用圖表繪製函數來繪製網絡路徑圖,代碼以下:app
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); }); }
六、經過以上步驟就完成了網絡路徑的二維繪製,三維繪製的話很簡單,只須要將MapView替換爲SceneView便可,代碼以下:echarts
let view = new SceneView({ container: "mapview", map: map, scale: 50000000, center: [107.246152,34.414465] });
咱們經過三篇文章,介紹了關於在eCharts中有關地理座標的圖表如何在ArcGIS的底圖上繪製的過程,這篇文章中的實現流程跟以前兩篇同樣,都是經過擴展EchartsLayer.js這個圖層類來實現的,因此後續你們有須要將eCharts中有關地理座標的圖表繪製到ArcGIS地圖上時,可用此擴展類來實現。關於將eCharts中普通的二維圖表繪製到ArcGIS底圖上的操做,由於不涉及地理座標的問題,因此咱們經過純前端的方式便可解決,具體實現請看這篇文章【01 【ArcGIS JS API + eCharts系列】實現地圖上二維圖表的繪製】。框架
TrafficNetwork組件代碼:函數
import React,{Component} from 'react'; import {loadModules} from 'esri-loader'; import echarts from 'echarts'; import './trafficNetwork.css'; import trafficData from './data/trafficData'; class TrafficNetwork extends Component { state = { busLines: null, series: null, } componentDidMount=() => { this._initMapView(); this._initData(); this._initCharts(); } //實例化地圖 _initMapView=() => { 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: 10, center: [116.403406,39.91582] //北京 116.403406,39.91582 成都 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); }); } //初始化數據 _initData=() => { const _self = this; let data = trafficData; let hStep = 300 / (data.length - 1); _self.state.busLines = [].concat.apply([], data.map(function (busLine, idx) { let prevPt; let points = []; for (let i = 0; i < busLine.length; i += 2) { let pt = [busLine[i], busLine[i + 1]]; if (i > 0) { pt = [ prevPt[0] + pt[0], prevPt[1] + pt[1] ]; } prevPt = pt; points.push([pt[0] / 1e4, pt[1] / 1e4]); } return { coords: points, lineStyle: { normal: { color: echarts.color.modifyHSL('#5A94DF', Math.round(hStep * idx)) } } } })) } //初始化圖表配置 _initCharts=() => { const _self = this; _self.state.series = [{ type: 'lines', coordinateSystem: 'arcgis', polyline: true, data: _self.state.busLines, silent: true, lineStyle: { // color: '#c23531', // color: 'rgb(200, 35, 45)', opacity: 0.2, width: 1 }, progressiveThreshold: 500, progressive: 200 }, { type: 'lines', coordinateSystem: 'arcgis', polyline: true, data: _self.state.busLines, lineStyle: { width: 0 }, effect: { constantSpeed: 20, show: true, trailLength: 0.1, symbolSize: 1.5 }, zlevel: 1 }] } //繪製圖表 _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 id="mapview"></div> ) } } export default TrafficNetwork;
EchartsLayer.min.js文件代碼:this
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;}});});