ECharts+百度地图网络拓扑图应用



前一篇谈及到了ECharts整合HT for eb网络扑图应用,后来在EChartsDemo中看到了有关空气质量的相关报表应用,就想将百度地图、EChartsHT for Web三者结合起来也做一个类似空气质量报告的报表+拓扑图应用,于是有了下面的


在这个Demo中,将GraphView拓扑图组件添加到百度地图组件中,覆盖在百度地图组件之上,并且在百度地图组件上和GraphView拓扑图组件上分别添加事件监听,相互同步经纬度和屏幕位置信息,从而来控制拓扑图上的组件位置固定在地图上,并在节点和节点之间的连线上加上了流动属性。右下角的图标框是采用HT for WebPanel面板组件结合ECharts图表组件完成的。

接下来我们来看看具体的代码实现:

 

1.百度地图是如何与HT for Web组件结合的;

伦理片 http://www.dotdy.com/


Js代码   收藏代码
  1. map = new BMap.Map("map");  
  2. var view = graphView.getView();  
  3. view.className = 'graphView';  
  4. var mapDiv = document.getElementById('map');  
  5. mapDiv.firstChild.firstChild.appendChild(view);  

 

首先需要在body中存在id为map的div,再通过百度地图的api来创建一个map地图对象,然后创建GraphView拓扑图组件,并获取GraphView组件中的view,最后将view添加到id为map的div的第二代孩子节点中。这时候问题就来了,为什么要将view添加到map的第二代孩子节点中呢,当你审查元素时你会发现这个div是百度地图的遮罩层,将view添加到上面,会使view会是在地图的顶层可见,不会被地图所遮挡。

 

2.百度地图和GraphView的事件监听;

 

Js代码   收藏代码
  1. map.addEventListener('moveend'function(e){  
  2.    resetPosition();  
  3. });  
  4. map.addEventListener('dragend'function(e){  
  5.    resetPosition();  
  6. });                                  
  7. map.addEventListener('zoomend'function(e){  
  8.     resetPosition();  
  9. });  
  10.   
  11. graphView.handleScroll = function(){};  
  12. graphView.handlePinch = function(){};  
  13.   
  14. function resetPosition(e){  
  15.     graphView.tx(0);  
  16.     graphView.ty(0);  
  17.     dataModel.each(function(data){  
  18.         var lonLat, position;  
  19.         if(data instanceof ht.HtmlNode){  
  20.             if(data.getId() != 'chartTotal') {  
  21.                 position = data.getHost().getPosition();  
  22.                 position = {x: position.x + 168, y: position.y + 158};  
  23.                 data.setPosition(position.x, position.y);  
  24.             }  
  25.         } else if(data instanceof ht.Node){  
  26.             lonLat = data.lonLat;  
  27.             position = map.pointToPixel(lonLat);  
  28.             data.setPosition(position.x,position.y);  
  29.         }  
  30.     });  
  31. }  

 

首先监听map的三个事件:moveend、 dragend、 zoomend,这三个事件做了同一件事--修改DataModel中所有data的position属性,让其在屏幕上的坐标与地图同步,然后将GraphView的Scroll和Pinch两个事件的执行函数设置为空函数,就是当监听到Scroll或者Pinch事件时不做任何的处理,将这两个事件交给map来处理。

 

resetPosition函数中,做的事情很简单:遍历DataModel中的data,根据它们各自在地图上的经纬度来换算成屏幕坐标,并将坐标设置到相应的data中,从而达到GraphView中的节点能够固定在地图上的效果。



 


3.创建右下角的图表组件:

Js代码   收藏代码
  1. ht.Chart = function(option){  
  2.     var self = this,  
  3.             view = self._view = document.createElement('div');  
  4.     view.style.position = 'absolute';  
  5.     view.style.setProperty('box-sizing''border-box'null);  
  6.     self._option = option;  
  7.     self._chart = echarts.init(self.getView());  
  8.     if(option)  
  9.         self._chart.setOption(option);  
  10.     self._FIRST = true;  
  11. };  
  12. ht.Default.def('ht.Chart', Object, {  
  13.     ms_v: 1,  
  14.     ms_fire: 1,  
  15.     ms_ac: ['chart''option''isFirst''view'],  
  16.     validateImpl: function(){  
  17.         var self = this,  
  18.                 chart = self._chart;  
  19.         chart.resize();  
  20.         if(self._FIRST){  
  21.             self._FIRST = false;  
  22.             chart.restore();  
  23.         }  
  24.     },  
  25.     setSize: function(w, h){  
  26.         var view = this._view;  
  27.         view.style.width = w + 'px';  
  28.         view.style.height = h + 'px';  
  29.     }  
  30. });  
  31.   
  32. function createPanel(title, width, height){  
  33.     chart = new ht.Chart(option);  
  34.     var c = chart.getChart();  
  35.     c.on(echarts.config.EVENT.LEGEND_SELECTED, legendSelectedFun);  
  36.     var chartPanel = new ht.widget.Panel({  
  37.         title: title,  
  38.         restoreToolTip: "Overview",  
  39.         width: width,  
  40.         contentHeight: height,  
  41.         narrowWhenCollapse: true,  
  42.         content: chart,  
  43.         expanded: true  
  44.     });  
  45.     chartPanel.setPositionRelativeTo("rightBottom");  
  46.     chartPanel.setPosition(0, 0);  
  47.     chartPanel.getView().style.margin = '10px';  
  48.   
  49.     document.body.appendChild(chartPanel.getView());  
  50. }  

首先定义了ht.Chart类,并实现了validateImpl方法,方法中处理的逻辑也很简单:在每次方法执行的时候调用图表的reset方法重新设定图标的展示大小,如果该方法是第一次执行的话,就调用图表的restore方法将图表还原为最原始的状态。会有这样的设计是因为ht.Chart类中的view是动态创建的,在没有添加到dom之前将一直存在于内存中,在内存中因为并没有浏览器宽高信息,所以div的实际宽高均为0,因此chartoption内容绘制在宽高为0div中,即使你resizechart,如果没用重置图表状态的话,图表状态将无法在图表上正常显示。

接下来就是创建panel图表组件了,这是HT for Web的Panel组件的基本用法,其中content属性的值可以是HT for Web的任何组件或div元素,如果是HT fro Web组件的话,该组件必须实现了validateImpl方法,因为在panel的属性变化后将会调用content对应组件的validateImpl方法来重新布局组件内容。

 

影音先锋电影 http://www.iskdy.com/ 

4.ECharts和GraphV拓扑图组件的交互:

Js代码   收藏代码
  1. legendSelectedFun = function(param) {  
  2.     if(chart._legendSelect){  
  3.         delete chart._legendSelect;  
  4.         return;  
  5.     }  
  6.     console.info(param);  
  7.     var id = nodeMap[param.target],  
  8.             dm = graphView.dm(),  
  9.             data = dm.getDataById(id),  
  10.             sm = dm.sm(),  
  11.             selection = sm.getSelection();  
  12.   
  13.     if(param.selected[param.target]) {  
  14.         sm.appendSelection([data]);  
  15.         if(selectionData.indexOf(param.target) < 0){  
  16.             selectionData.push(param.target);  
  17.         }  
  18.     }else {  
  19.         sm.removeSelection([data]);  
  20.         var index = selectionData.indexOf(param.target);  
  21.         if(index >= 0){  
  22.             selectionData.splice(index, 1);  
  23.         }  
  24.     }  
  25.     sm.setSelection(selection.toArray());  
  26. };  
  27.   
  28. graphView.mi(function(e){  
  29.     console.info(e.kind, e.data);  
  30.     var c = chart.getChart(),  
  31.             legend = c.component.legend,  
  32.             selectedMap = legend.getSelectedMap();  
  33.   
  34.     if(e.kind === 'endRectSelect'){  
  35.         chart._legendSelect = true;  
  36.         for(var name in notes){  
  37.             legend.setSelected(name, false);  
  38.         }  
  39.         notes = {};  
  40.         graphView.dm().sm().each(function(data){  
  41.             var note = data.s('note');  
  42.             if(note)  
  43.                 notes[note] = 1;  
  44.         });  
  45.         for(var name in notes){  
  46.             legend.setSelected(name, true);  
  47.         }  
  48.     } else if(e.kind === 'clickData'){  
  49.         chart._legendSelect = true;  
  50.         var data = e.data;  
  51.         if(data instanceof ht.Node){  
  52.             var note = data.s('note');  
  53.   
  54.             if(note){  
  55.                 var selected = legend.isSelected(note);  
  56.                 if(selected){  
  57.                     graphView.dm().sm().removeSelection([data]);  
  58.                 }  
  59.                 legend.setSelected(note, !selected);  
  60.             }  
  61.         }  
  62.     }  
  63. });  

legendSelectedFun函数是EChart图表的legend插件选中事件监听,其中处理的逻辑是:当legend插件中的某个节点被选中了,也选中在GraphView拓扑图中对应的节点,当取消选中是,也取消选中GraphView拓扑图中对应的节点。

GraphView中添加交互监听,如果在GraphView中做了框选操作,在框选结束后,将原本legend插件上被选中的节点取消选中,然后再获取被选中节点,并在legend插件上选中对应节点;当GraphView上的节点被选中,则根据legend插件中对应节点选中情况来决定legend插件中的节点和graphView上的节点是否选中。

 

在GraphView交互中,我往chart实例中添加了_legendSelect变量,该变量的设定是为了阻止在GraphView交互中修改legend插件的节点属性后回调legendSelectedFun回调函数做修改GraphView中节点属性操作。


今天就写到这吧,希望这篇文章能够帮到那些有地图、拓扑图、图表相结合需求的朋友,在设计上可能想法还不够成熟,希望大家不吝赐教。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值