Skip to content

Commit 77f1dc7

Browse files
committed
add selection feature
Select a node or link while holding the CTRL key.
1 parent b6b186f commit 77f1dc7

File tree

4 files changed

+178
-0
lines changed

4 files changed

+178
-0
lines changed

src/js/netjsongraph.config.js

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,39 @@ const NetJSONGraphDefaultConfig = {
8585
legendHoverLink: true,
8686
emphasis: {
8787
focus: "none",
88+
scale: 2,
8889
lineStyle: {
8990
color: "#3acc38",
9091
opacity: 1,
9192
},
93+
itemStyle: {
94+
//color: "#3acc38",
95+
color: {
96+
type: "radial",
97+
x: 0.5,
98+
y: 0.5,
99+
r: 0.5,
100+
colorStops: [
101+
{
102+
offset: 0,
103+
color: "#ffebc4",
104+
},
105+
{
106+
offset: 0.5,
107+
color: "#ffebc4",
108+
},
109+
{
110+
offset: 0.51,
111+
color: "#ffffff33",
112+
},
113+
{
114+
offset: 1,
115+
color: "#ffffff33",
116+
},
117+
],
118+
opacity: 1,
119+
},
120+
},
92121
},
93122
nodeStyle: {
94123
color: "#ffebc4",
@@ -172,6 +201,37 @@ const NetJSONGraphDefaultConfig = {
172201
nodeStyle: {
173202
color: "#1566a9",
174203
},
204+
emphasis: {
205+
focus: "none",
206+
scale: 2,
207+
itemStyle: {
208+
color: {
209+
type: "radial",
210+
x: 0.5,
211+
y: 0.5,
212+
r: 0.5,
213+
colorStops: [
214+
{
215+
offset: 0,
216+
color: "#1566a9",
217+
},
218+
{
219+
offset: 0.5,
220+
color: "#1566a9",
221+
},
222+
{
223+
offset: 0.51,
224+
color: "green",
225+
},
226+
{
227+
offset: 1,
228+
color: "green",
229+
},
230+
],
231+
opacity: 1,
232+
},
233+
},
234+
},
175235
nodeSize: "17",
176236
},
177237
linkConfig: {

src/js/netjsongraph.core.js

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,119 @@
11
import NetJSONGraphDefaultConfig from "./netjsongraph.config";
22
import NetJSONGraphUpdate from "./netjsongraph.update";
33

4+
class Selection {
5+
constructor() {
6+
this.selected = new Set();
7+
}
8+
9+
getSetId(item) {
10+
if (item.node) {
11+
// map node
12+
return item.node.id;
13+
} else if (item.link) {
14+
// map link
15+
return (item.link.source + "=>" + item.link.target);
16+
} else if (item.id) {
17+
// graph node
18+
return item.id;
19+
} else {
20+
// graph link
21+
return (item.source + "=>" + item.target);
22+
}
23+
}
24+
25+
isSelected(item) {
26+
let id = this.getSetId(item);
27+
return this.selected.has(id);
28+
}
29+
30+
toggleSelection(item) {
31+
let id = this.getSetId(item);
32+
33+
if (this.selected.has(id)) {
34+
this.selected.delete(id)
35+
return false;
36+
} else {
37+
this.selected.add(id);
38+
return true;
39+
}
40+
}
41+
42+
changeSelection(echarts, params) {
43+
const multiSelectKey = (window.event.ctrlKey || window.event.metaKey);
44+
const isSelectionEmpty = (this.selected.size === 0);
45+
46+
if (multiSelectKey) {
47+
if (this.toggleSelection(params.data)) {
48+
echarts.dispatchAction(
49+
{ type: 'highlight', seriesIndex: params.seriesIndex, dataType: params.dataType, dataIndex: params.dataIndex}
50+
)
51+
} else {
52+
echarts.dispatchAction(
53+
{ type: 'downplay', seriesIndex: params.seriesIndex, dataType: params.dataType, dataIndex: params.dataIndex}
54+
)
55+
}
56+
} else if (!isSelectionEmpty) {
57+
const option = echarts.getOption();
58+
let nodeIndexes = [];
59+
let linkIndexes = [];
60+
if (option.leaflet) {
61+
// map
62+
const nodeData = option.leaflet[0].mapOptions.nodeConfig.data;
63+
const linkData = option.leaflet[0].mapOptions.linkConfig.data;
64+
nodeIndexes = nodeData.map((node, index) => index);
65+
linkIndexes = linkData.map((link, index) => index);
66+
} else {
67+
// graph
68+
const nodeData = option.series[0].nodes;
69+
const linkData = option.series[0].links;
70+
nodeIndexes = nodeData.map((node, index) => index);
71+
linkIndexes = linkData.map((link, index) => index);
72+
}
73+
74+
// downplay all items
75+
echarts.dispatchAction(
76+
{ type: 'downplay', seriesIndex: 0, batch: [
77+
{dataType: "node", dataIndex: nodeIndexes},
78+
{dataType: "edge", dataIndex: linkIndexes},
79+
]
80+
}
81+
)
82+
83+
this.selected.clear();
84+
}
85+
}
86+
87+
// called when switching between graph/map view
88+
highlightSelected(echarts) {
89+
const option = echarts.getOption();
90+
91+
let nodeIndexes = [];
92+
let linkIndexes = [];
93+
if (option.leaflet) {
94+
// map
95+
const nodeData = option.leaflet[0].mapOptions.nodeConfig.data;
96+
const linkData = option.leaflet[0].mapOptions.linkConfig.data;
97+
nodeIndexes = nodeData.map((node, index) => this.isSelected(node) ? index : -1);
98+
linkIndexes = linkData.map((link, index) => this.isSelected(link) ? index : -1);
99+
} else {
100+
// graph
101+
const nodeData = option.series[0].nodes;
102+
const linkData = option.series[0].links;
103+
nodeIndexes = nodeData.map((node, index) => this.isSelected(node) ? index : -1);
104+
linkIndexes = linkData.map((link, index) => this.isSelected(link) ? index : -1);
105+
}
106+
107+
echarts.dispatchAction(
108+
{ type: 'highlight', seriesIndex: 0, batch: [
109+
{dataType: "node", dataIndex: nodeIndexes},
110+
{dataType: "edge", dataIndex: linkIndexes},
111+
]
112+
}
113+
)
114+
}
115+
}
116+
4117
class NetJSONGraph {
5118
/**
6119
* @constructor
@@ -10,6 +123,7 @@ class NetJSONGraph {
10123
*/
11124
constructor(JSONParam) {
12125
this.utils = new NetJSONGraphUpdate();
126+
this.selection = new Selection();
13127
this.config = {...NetJSONGraphDefaultConfig};
14128
this.JSONParam = this.utils.isArray(JSONParam) ? JSONParam : [JSONParam];
15129
}

src/js/netjsongraph.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,8 @@ class NetJSONGraph {
151151
document.querySelector(".leaflet-control-zoom").style.display =
152152
"block";
153153
}
154+
155+
this.selection.highlightSelected(this.echarts);
154156
};
155157
}
156158
this.utils.hideLoading.call(this);

src/js/netjsongraph.render.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ class NetJSONGraphRender {
9898
echartsLayer.on(
9999
"click",
100100
(params) => {
101+
self.selection.changeSelection(self.echarts, params);
102+
101103
const clickElement = configs.onClickElement.bind(self);
102104
if (params.componentSubType === "graph") {
103105
return clickElement(

0 commit comments

Comments
 (0)