百度地圖、ECharts整合HT for Web網絡拓撲圖應用
2015-04-16 00:07
RTdo
閱讀(493)
評論(0)
編輯
收藏
舉報
直擊現場
百度地圖、ECharts整合HT for Web網絡拓撲圖應用
發表于3周前(2015-03-23 01:32) 閱讀(1320) | 評論(5) 78人收藏此文章, 我要收藏
贊8
慕課網,程式員升職加薪神器,點選免費學習
摘要 前一篇談及到了ECharts整合HT for Web的網絡拓撲圖應用,後來在ECharts的Demo中看到了有關空氣品質的相關報表應用,就想将百度地圖、ECharts和HT for Web三者結合起來也做一個類似空氣品質報告的報表+拓撲圖應用。
hightopo HTforWeb 網絡拓撲圖 ECharts 百度地圖
前一篇談及到了ECharts整合HT for Web的網絡拓撲圖應用,後來在ECharts的Demo中看到了有關空氣品質的相關報表應用,就想将百度地圖、ECharts和HT for Web三者結合起來也做一個類似空氣品質報告的報表+拓撲圖應用,于是有了下面的Demo:
![]()
百度地圖、ECharts整合HT for Web網絡拓撲圖應用 - RTdo 在這個Demo中,将GraphView拓撲圖元件添加到百度地圖元件中,覆寫在百度地圖元件之上,并且在百度地圖元件上和GraphView拓撲圖元件上分别添加事件監聽,互相同步經緯度和螢幕位置資訊,進而來控制拓撲圖上的元件位置固定在地圖上,并在節點和節點之間的連線上加上了流動屬性。右下角的圖示框是采用HT for Web的Panel面闆元件結合ECharts圖表元件完成的。
接下來我們來看看具體的代碼實作:
1. 百度地圖是如何與HT for Web元件結合的;
?
1
2
3
4
5
map =
new
BMap.Map(
"map"
);
var
view = graphView.getView();
view.className =
\'graphView\'
;
var
mapDiv = document.getElementById(
\'map\'
);
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的事件監聽;
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
map.addEventListener(
\'moveend\'
,
function
(e){
resetPosition();
});
map.addEventListener(
\'dragend\'
,
function
(e){
resetPosition();
});
map.addEventListener(
\'zoomend\'
,
function
(e){
resetPosition();
});
graphView.handleScroll =
function
(){};
graphView.handlePinch =
function
(){};
function
resetPosition(e){
graphView.tx(0);
graphView.ty(0);
dataModel.each(
function
(data){
var
lonLat, position;
if
(data
instanceof
ht.HtmlNode){
if
(data.getId() !=
\'chartTotal\'
) {
position = data.getHost().getPosition();
position = {x: position.x + 168, y: position.y + 158};
data.setPosition(position.x, position.y);
}
}
else
if
(data
instanceof
ht.Node){
lonLat = data.lonLat;
position = map.pointToPixel(lonLat);
data.setPosition(position.x,position.y);
}
});
}
首先監聽map的三個事件:moveend、 dragend、 zoomend,這三個事件做了同一件事--修改DataModel中所有data的position屬性,讓其在螢幕上的坐标與地圖同步,然後将GraphView的Scroll和Pinch兩個事件的執行函數設定為空函數,就是當監聽到Scroll或者Pinch事件時不做任何的處理,将這兩個事件交給map來處理。
在resetPosition函數中,做的事情很簡單:周遊DataModel中的data,根據它們各自在地圖上的經緯度來換算成螢幕坐标,并将坐标設定到相應的data中,進而達到GraphView中的節點能夠固定在地圖上的效果。
![]()
百度地圖、ECharts整合HT for Web網絡拓撲圖應用 - RTdo ![]()
百度地圖、ECharts整合HT for Web網絡拓撲圖應用 - RTdo 3. 建立右下角的圖表元件:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
ht.Chart =
function
(option){
var
self =
this
,
view = self._view = document.createElement(
\'div\'
);
view.style.position =
\'absolute\'
;
view.style.setProperty(
\'box-sizing\'
,
\'border-box\'
,
null
);
self._option = option;
self._chart = echarts.init(self.getView());
if
(option)
self._chart.setOption(option);
self._FIRST =
true
;
};
ht.Default.def(
\'ht.Chart\'
, Object, {
ms_v: 1,
ms_fire: 1,
ms_ac: [
\'chart\'
,
\'option\'
,
\'isFirst\'
,
\'view\'
],
validateImpl:
function
(){
var
self =
this
,
chart = self._chart;
chart.resize();
if
(self._FIRST){
self._FIRST =
false
;
chart.restore();
}
},
setSize:
function
(w, h){
var
view =
this
._view;
view.style.width = w +
\'px\'
;
view.style.height = h +
\'px\'
;
}
});
function
createPanel(title, width, height){
chart =
new
ht.Chart(option);
var
c = chart.getChart();
c.on(echarts.config.EVENT.LEGEND_SELECTED, legendSelectedFun);
var
chartPanel =
new
ht.widget.Panel({
title: title,
restoreToolTip:
"Overview"
,
width: width,
contentHeight: height,
narrowWhenCollapse:
true
,
content: chart,
expanded:
true
});
chartPanel.setPositionRelativeTo(
"rightBottom"
);
chartPanel.setPosition(0, 0);
chartPanel.getView().style.margin =
\'10px\'
;
document.body.appendChild(chartPanel.getView());
}
首先定義了ht.Chart類,并實作了validateImpl方法,方法中處理的邏輯也很簡單:在每次方法執行的時候調用圖表的reset方法重新設定圖示的展示大小,如果該方法是第一次執行的話,就調用圖表的restore方法将圖表還原為最原始的狀态。會有這樣的設計是因為ht.Chart類中的view是動态建立的,在沒有添加到dom之前将一直存在于記憶體中,在記憶體中因為并沒有浏覽器寬高資訊,是以div的實際寬高均為0,是以chart将option内容繪制在寬高為0的div中,即使你resize了chart,如果沒用重置圖表狀态的話,圖表狀态将無法在圖表上正常顯示。
接下來就是建立panel圖表元件了,這是HT for Web的Panel元件的基本用法,其中content屬性的值可以是HT for Web的任何元件或div元素,如果是HT fro Web元件的話,該元件必須實作了validateImpl方法,因為在panel的屬性變化後将會調用content對應元件的validateImpl方法來重新布局元件内容。
4. ECharts和GraphView拓撲圖元件的互動:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
legendSelectedFun =
function
(param) {
if
(chart._legendSelect){
delete
chart._legendSelect;
return
;
}
console.info(param);
var
id = nodeMap[param.target],
dm = graphView.dm(),
data = dm.getDataById(id),
sm = dm.sm(),
selection = sm.getSelection();
if
(param.selected[param.target]) {
sm.appendSelection([data]);
if
(selectionData.indexOf(param.target) < 0){
selectionData.push(param.target);
}
}
else
{
sm.removeSelection([data]);
var
index = selectionData.indexOf(param.target);
if
(index >= 0){
selectionData.splice(index, 1);
}
}
sm.setSelection(selection.toArray());
};
graphView.mi(
function
(e){
console.info(e.kind, e.data);
var
c = chart.getChart(),
legend = c.component.legend,
selectedMap = legend.getSelectedMap();
if
(e.kind ===
\'endRectSelect\'
){
chart._legendSelect =
true
;
for
(
var
name
in
notes){
legend.setSelected(name,
false
);
}
notes = {};
graphView.dm().sm().each(
function
(data){
var
note = data.s(
\'note\'
);
if
(note)
notes[note] = 1;
});
for
(
var
name
in
notes){
legend.setSelected(name,
true
);
}
}
else
if
(e.kind ===
\'clickData\'
){
chart._legendSelect =
true
;
var
data = e.data;
if
(data
instanceof
ht.Node){
var
note = data.s(
\'note\'
);
if
(note){
var
selected = legend.isSelected(note);
if
(selected){
graphView.dm().sm().removeSelection([data]);
}
legend.setSelected(note, !selected);
}
}
}
});
legendSelectedFun函數是EChart圖表的legend插件選中事件監聽,其中處理的邏輯是:當legend插件中的某個節點被選中了,也選中在GraphView拓撲圖中對應的節點,當取消選中是,也取消選中GraphView拓撲圖中對應的節點。
在GraphView中添加互動監聽,如果在GraphView中做了框選操作,在框選結束後,将原本legend插件上被選中的節點取消選中,然後再擷取被選中節點,并在legend插件上選中對應節點;當GraphView上的節點被選中,則根據legend插件中對應節點選中情況來決定legend插件中的節點和graphView上的節點是否選中。
在GraphView互動中,我往chart執行個體中添加了_legendSelect變量,該變量的設定是為了阻止在GraphView互動中修改legend插件的節點屬性後回調legendSelectedFun回調函數做修改GraphView中節點屬性操作。
今天就寫到這吧,希望這篇文章能夠幫到那些有地圖、拓撲圖、圖表相結合需求的朋友,在設計上可能想法還不夠成熟,希望大家不吝賜教。![]()
百度地圖、ECharts整合HT for Web網絡拓撲圖應用 - RTdo
-
分類 App
, Javascript