概述

前面两篇文章通过扩展EchartsLayer.js这个图层类,实现了使用ArcGIS JS API和eCharts,在二维和三维场景下绘制迁徙图和散点图。这篇文章继续通过绘制网络路径图的例子,再来验证下我们扩展的这个图层类是否可用,先来看下最终效果:

实现思路

迁徙图、散点图和网络路径图这种图表跟地理坐标关系紧密,所以仅仅通过第一篇二维普通图表绘制的方式是无法实现这类图表绘制的,所以就需要我们来扩展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、通过上述操作实例化完一张二维地图后,我们接下来就要进行网络路径图的绘制操作了,在开始之前我们需要数据,就是关于网络路径的坐标数据和相应权重值的数据,我将它存在了一份JS文件里,此文件比较大,所以并不打算在此处粘贴出来,有需要的可以到此地址下载。

3、下载到数据后,将数据拷贝至demo代码目录下,然后在组件代码中引入,此处我们是将它引入到我们新建的TrafficNetwork组件目录下,然后编写数据处理的函数,对下载下来的数据进行初始化处理,代码如下:

//初始化数据

_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))

}

}

}

}))

}

4、数据初始完成后,我们进行网络路径图表的绘制信息配置,也就是初始化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

}]

}

5、接下来和之前文章的流程一样,监听地图的绘制完成事件,然后调用图表绘制函数来绘制网络路径图,代码如下:

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);

});

}

6、通过以上步骤就完成了网络路径的二维绘制,三维绘制的话很简单,只需要将MapView替换为SceneView即可,代码如下:

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 (

)

}

}

export default TrafficNetwork;

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;}});});

三维地图前端arcgis_【ArcGIS JS API + eCharts系列】实现二、三维网络路径图的绘制...相关推荐

  1. 04 【ArcGIS JS API + eCharts系列】实现二、三维网络路径图的绘制

    概述 前面两篇文章通过扩展EchartsLayer.js这个图层类,实现了使用ArcGIS JS API和eCharts,在二维和三维场景下绘制迁徙图和散点图.这篇文章继续通过绘制网络路径图的例子,再 ...

  2. 02 【ArcGIS JS API + eCharts系列】实现二、三维迁徙图的绘制

    概述 上一篇文章通过纯前端的方式实现了ArcGIS JS API和eCharts的普通二维图表绘制,因为这些图表绘制其实是跟地理坐标无关的,只需要设置图表的位置即可,所以仅仅用了纯前端的方式去实现.这 ...

  3. 03 【ArcGIS JS API + eCharts系列】实现二、三维散点图的绘制

    概述 上一篇文章中我们介绍了如何使用ArcGIS JS API和eCharts结合,在二维和三维场景下绘制迁徙图.这篇文章我们来介绍下如何在二维和三维场景下绘制散点图,其实散点图跟迁徙图一样,它的绘制 ...

  4. ArcGIS JS API 4.x(二) 加载 3.x所说的动态地图服务图层

    前言:在使用arcgis js api 3.x的时候,有切片地图服务和动态地图服务,从3.x到4.x版本过渡的时候,希望能够找到和3.x对应的类,在上篇博客中,我们找到了和ArcGISTiledMap ...

  5. 三维地图前端arcgis_通过ArcGIS创建2D及3D地图

    前端开发中,GIS的用途很明确,就是用来做地图.你对地图的操作,不管是图形的绘制还是实体的添加都是在基础地图之上.本文将向你讲诉如何使用GIS创建基础地图以一些API的使用. 前提 在编写代码之前先简 ...

  6. ArcGIS JS API实现地图场景视频融合

    ArcGIS JS API实现地图场景视频融合 效果展示 实现步骤 1.创建地图场景 2.引入相应模块并创建地图场景 3.获取点坐标 4.生成网格 5.生成图形并添加进场景中 总结 完整代码 效果展示 ...

  7. 基于ArcGIS JS API 4.11实现对FeatureLayer的多变量渲染

    文章目录 需求背景 需求分析 开发过程 效果图 注意事项 参考链接 在线示例 需求背景 有一个二维数组,里面包含几万个表示高度的值,现在要把这些高度值在地图上展示出来.可以通过小立方体的方式展现,长宽 ...

  8. 08 ArcGIS JS API 4.15实现萤火虫效果

    概述 前几天在看帖子的时候发现有大佬使用ArcGIS Pro和Portal制作了萤火虫的渲染效果,感觉前端可视化的时候还不错,所以自己也将实例数据下载下来之后用ArcGIS JS API来实现了一下, ...

  9. ArcGIS JS API 4.X实现动态地图服务子图层显隐控制

    ArcGIS JS API 4.X实现动态地图服务子图层显隐控制 文章目录 ArcGIS JS API 4.X实现动态地图服务子图层显隐控制 使用场景 官网示例 注意事项 使用场景 图层控制功能 官网 ...

最新文章

  1. 告别AI模型黑盒子:可解释性将是数据科学的下一个“超能力”
  2. XML(一)XML大揭秘
  3. mos管电路_【鼎阳硬件智库原创︱电源】 MOS管驱动电路的设计
  4. xstream不映射字段_Mybatis_day03:输入映射和输出映射
  5. spring+mybatis+atomikos 实现JTA事务
  6. Cookie和Session-学习笔记02【Cookie案例、JSP改造Cookie案例】
  7. 生成Geometry
  8. 华为动态NAT小实验演示
  9. 经典编程问题之:选择排序、冒泡排序、汉诺塔游戏,均用js代码实现
  10. codeforces 688D D. Remainders Game(中国剩余定理)
  11. 勒索病毒运营团伙的运作流程
  12. php如何控制用户数,PHP统计当前在线用户数实例讲解
  13. pulse 去马赛克软件_Github高赞:打马赛克=形同虚设,AI看透你一切小心思
  14. 几款开源的Windows界面库
  15. oracle mysql认证考试流程_oraclemysql认证考试流程
  16. CommandName属性和CommandArgument属性
  17. STM32F205 PWM配置
  18. vue集成wangeditor3.0版本 解决光标乱跳等问题
  19. 基于VUE + Echarts 实现可视化数据大屏智慧校园可视化
  20. 不定宽高,实现盒子左右垂直居中

热门文章

  1. 读《品人录》——雍正
  2. (转)ASP.NET MVC 学习第一天
  3. 如何排查网络丢包问题
  4. 2022中国可持续消费报告:近半数消费者将月度消费2-5成用于低碳产品 | 美通社头条...
  5. android nougat honr7,Honor 荣耀7 最新全功能NFC 体验
  6. 贱人就是矫情——当打假成为一门生意
  7. Android音视频视频基础(H264)
  8. 坐标+半径 生成 geohash
  9. 多媒体技术基本概念汇总
  10. Keystone详解