我正在绘制四个具有相同数据的网络图,但是使用不同的属性为节点着色。当前,我能够生成所有4个网络,并且对于每个网络,我都可以双击一个节点以查看该网络的连接节点。我的问题是如何扩展此功能,以便在单击任何图形网络上的节点时,其他3个节点也会向我显示我单击的节点以及其中的连接节点。
之前Mouseover event on two charts at the same time d3.js提出的这个问题对于饼图也做了类似的事情,但是我不确定如何使它适应我的代码。
var drawNetworkFunction = function(descriptor, chartId) {
var width = 470;
var height = 310;
var toggle = 0;
var activenode;
var svg = d3.select(chartId).append("svg")
.attr("width", width)
.attr("height", height);
var container = svg.append("g")
.attr("class", "everything");
if (descriptor == "id" || descriptor == "cluster") {
var color = d3.scaleOrdinal(d3.schemeCategory10);
}
var simulation = d3.forceSimulation()
.force("link", d3.forceLink().id(function(d) {
return d.id;
}))
.force("charge", d3.forceManyBody().strength(-7))
.force("center", d3.forceCenter(width / 2, height / 2));
d3.json("Perovskite_info.json", function(graph) {
if (descriptor == "cohesive") {
var cscale = d3.scaleLinear()
.domain([1.6, 7.2])
.range([0, 1]);
} else if (descriptor == "similarity") {
var cscale = d3.scaleLinear()
.domain([0, 1])
.range([0, 1]);
}
var link = svg.append("g")
.attr("class", "links")
.selectAll("line")
.data(graph.links)
.enter().append("line")
.attr("stroke", "#000")
.attr("stroke-opacity", "0.1");
var node = svg.append("g")
.attr("class", "nodes")
.selectAll("circle")
.data(graph.nodes)
.attr("pvs_id", function(d) { return d.id; })
.enter().append("circle")
.attr("r", 5)
.attr("fill", function(d) {
var col = '';
if (descriptor == "id") {
col = color(d.group);
} else if (descriptor == "cluster") {
col = color(d.cluster);
} else if (descriptor == "cohesive") {
col = d3.interpolatePurples(cscale(d.cohesive));
} else if (descriptor == "similarity") {
col = d3.interpolateReds(cscale(d.similarity));
}
return col;
})
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended))
.on("dblclick", connectedNodes);
node.append("title")
.text(function(d) {
return ["Perovskite :" + d.id,
"Cluster :" + d.cluster,
"Cohesive Energy :" + d.cohesive,
"Similarity to CaTiO3 :" + d.similarity
];
});
simulation
.nodes(graph.nodes)
.on("tick", ticked);
simulation.force("link")
.links(graph.links);
function ticked() {
link
.attr("x1", function(d) {
return d.source.x;
})
.attr("y1", function(d) {
return d.source.y;
})
.attr("x2", function(d) {
return d.target.x;
})
.attr("y2", function(d) {
return d.target.y;
});
node
.attr("cx", function(d) {
return d.x;
})
.attr("cy", function(d) {
return d.y;
});
}
var linkedByIndex = {};
for (i = 0; i < graph.nodes.length; i++) {
linkedByIndex[i + "," + i] = 1;
};
graph.links.forEach(function(d) {
linkedByIndex[d.source.index + "," + d.target.index] = 1;
});
function neighboring(a, b) {
return linkedByIndex[a.index + "," + b.index];
}
function HS_f(activenode) {
if (activenode != null) {
var fing_plot = d3.select("#HSA_fingerprint")
.append("svg")
.attr("id", "fin_pl")
.attr("width", 300)
.attr("height", 300);
fing_plot.append('svg:image')
.attr("xlink:href", function() { return "./finger_prints_lo/" + activenode + "_lo.png" })
.attr("width", 250)
.attr("height", 250);
return fing_plot;
}
}
function connectedNodes() {
if (toggle == 0) {
d = d3.select(this).node().__data__;
node.style("opacity", function(o) {
return neighboring(d, o) | neighboring(o, d) ? 1 : 0.15;
});
toggle = 1;
activenode = d.id;
window.activenode = activenode;
console.log(activenode);
HS_f(activenode);
} else {
node.style("opacity", 1);;
toggle = 0;
d3.select("#fin_pl").remove();
}
}
});
function dragstarted(d) {
if (!d3.event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}
function dragged(d) {
d.fx = d3.event.x;
d.fy = d3.event.y;
}
function dragended(d) {
if (!d3.event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}
return svg;
}
有关json文件,请参见链接:https://api.myjson.com/bins/m3gd8
我的html文件也在下面:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script type=" text/javascript " src="http://code.jquery.com/jquery-latest.js "></script>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-color.v1.min.js"></script>
<script src="https://d3js.org/d3-interpolate.v1.min.js"></script>
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
<script src="https://d3js.org/d3-dispatch.v1.min.js"></script>
<script src="draw_net.js"></script>
<title>Library of Perovskite structures from Materials Project Database</title>
<div id="title_main">
<h2>Graph Network of Perovskite structures from Materials Project Database</h2>
</div>
</head>
<body>
<link rel="stylesheet" href="pvs-net.css" />
<div style="width: 80%; float:left; overflow: auto;">
<div id="Perovskite_Network">
<div style="width: 50%; float:left;">
<div id="Network1">
<div id="title_1">
<h3>Isomap Graph Network</h3>
<script>
var Net1 = drawNetworkFunction('id', '#Network1');
</script>
</div>
</div>
<div id="Network2">
<div style="width: 50%; float:left; overflow: auto;"></div>
<div id="title_2">
<h3>Spectral Clustering on Isomap Graph Network</h3>
<script>
var Net2 = drawNetworkFunction('cluster', '#Network2');
</script>
</div>
</div>
</div>
<div style="width: 50%; float:right; overflow: auto;">
<div id="Network3">
<div id="title_3">
<h3>Calculated Cohesive Energy</h3>
<script>
var Net3 = drawNetworkFunction('cohesive', '#Network3');
</script>
</div>
</div>
<div id="Network4">
<div id="title_4">
<h3>Similarity score against CaTiO3</h3>
<script>
var Net4 = drawNetworkFunction('similarity', '#Network4');
</script>
</div>
</div>
</div>
</div>
</div>
</div>
<div style="width: 20%; height: 500px; float:right;">
<div id="HSA_fingerprint">
<div id="title">
<h3>Hirschfeld Surface Fingerprint Plot</h3>
</div>
</div>
</div>
</body>
</html>
答案 0 :(得分:0)
很高兴您收到了数据和HTML。它使调试和提出解决方案变得更加容易。
我刚刚在connectedNodes
函数中更改了几行代码:
我将其替换为node.style("opacity", function(o) {...})
:
d3.select('#Perovskite_Network').selectAll('.nodes').selectAll('circle').style("opacity", function(o) {
return neighboring(d, o) | neighboring(o, d) ? 1 : 0.15;
});
这将从所有SVG中选择所有circle
。让我知道这是否无济于事,或者您是否需要任何改进。
代码段:
var drawNetworkFunction = function(descriptor, chartId) {
var width = 470;
var height = 310;
var toggle = 0;
var activenode;
var svg = d3.select(chartId).append("svg")
.attr("width", width)
.attr("height", height);
var container = svg.append("g")
.attr("class", "everything");
if (descriptor == "id" || descriptor == "cluster") {
var color = d3.scaleOrdinal(d3.schemeCategory10);
}
var simulation = d3.forceSimulation()
.force("link", d3.forceLink().id(function(d) {
return d.id;
}))
.force("charge", d3.forceManyBody().strength(-7))
.force("center", d3.forceCenter(width / 2, height / 2));
d3.json("https://api.myjson.com/bins/m3gd8", function(graph) {
if (descriptor == "cohesive") {
var cscale = d3.scaleLinear()
.domain([1.6, 7.2])
.range([0, 1]);
} else if (descriptor == "similarity") {
var cscale = d3.scaleLinear()
.domain([0, 1])
.range([0, 1]);
}
var link = svg.append("g")
.attr("class", "links")
.selectAll("line")
.data(graph.links)
.enter().append("line")
.attr("stroke", "#000")
.attr("stroke-opacity", "0.1");
var node = svg.append("g")
.attr("class", "nodes")
.selectAll("circle")
.data(graph.nodes)
.attr("pvs_id", function(d) { return d.id; })
.enter().append("circle")
.attr("r", 5)
.attr("fill", function(d) {
var col = '';
if (descriptor == "id") {
col = color(d.group);
} else if (descriptor == "cluster") {
col = color(d.cluster);
} else if (descriptor == "cohesive") {
col = d3.interpolatePurples(cscale(d.cohesive));
} else if (descriptor == "similarity") {
col = d3.interpolateReds(cscale(d.similarity));
}
return col;
})
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended))
.on("dblclick", connectedNodes);
node.append("title")
.text(function(d) {
return ["Perovskite :" + d.id,
"Cluster :" + d.cluster,
"Cohesive Energy :" + d.cohesive,
"Similarity to CaTiO3 :" + d.similarity
];
});
simulation
.nodes(graph.nodes)
.on("tick", ticked);
simulation.force("link")
.links(graph.links);
function ticked() {
link
.attr("x1", function(d) {
return d.source.x;
})
.attr("y1", function(d) {
return d.source.y;
})
.attr("x2", function(d) {
return d.target.x;
})
.attr("y2", function(d) {
return d.target.y;
});
node
.attr("cx", function(d) {
return d.x;
})
.attr("cy", function(d) {
return d.y;
});
}
var linkedByIndex = {};
for (i = 0; i < graph.nodes.length; i++) {
linkedByIndex[i + "," + i] = 1;
}
graph.links.forEach(function(d) {
linkedByIndex[d.source.index + "," + d.target.index] = 1;
});
function neighboring(a, b) {
return linkedByIndex[a.index + "," + b.index];
}
function HS_f(activenode) {
if (activenode != null) {
var fing_plot = d3.select("#HSA_fingerprint")
.append("svg")
.attr("id", "fin_pl")
.attr("width", 300)
.attr("height", 300);
fing_plot.append('svg:image')
.attr("xlink:href", function() { return "./finger_prints_lo/" + activenode + "_lo.png" })
.attr("width", 250)
.attr("height", 250);
return fing_plot;
}
}
function connectedNodes() {
if (toggle == 0) {
d = d3.select(this).node().__data__;
d3.select('#Perovskite_Network').selectAll('.nodes').selectAll('circle').style("opacity", function(o) {
return neighboring(d, o) | neighboring(o, d) ? 1 : 0.15;
});
toggle = 1;
activenode = d.id;
window.activenode = activenode;
//console.log(activenode);
HS_f(activenode);
} else {
d3.select('#Perovskite_Network').selectAll('.nodes').selectAll('circle').style("opacity", 1);
toggle = 0;
d3.select("#fin_pl").remove();
}
}
});
function dragstarted(d) {
if (!d3.event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}
function dragged(d) {
d.fx = d3.event.x;
d.fy = d3.event.y;
}
function dragended(d) {
if (!d3.event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}
return svg;
}
drawNetworkFunction('id', '#Network1');
drawNetworkFunction('cluster', '#Network2');
drawNetworkFunction('cohesive', '#Network3');
drawNetworkFunction('similarity', '#Network4');
<meta charset="utf-8">
<script type=" text/javascript " src="http://code.jquery.com/jquery-latest.js "></script>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-color.v1.min.js"></script>
<script src="https://d3js.org/d3-interpolate.v1.min.js"></script>
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
<script src="https://d3js.org/d3-dispatch.v1.min.js"></script>
<script src="draw_net.js"></script>
<title>Library of Perovskite structures from Materials Project Database</title>
<div id="title_main">
<h2>Graph Network of Perovskite structures from Materials Project Database</h2>
</div>
<link rel="stylesheet" href="pvs-net.css" />
<div style="width: 80%; float:left; overflow: auto;">
<div id="Perovskite_Network">
<div style="width: 50%; float:left;">
<div id="Network1">
<div id="title_1">
<h3>Isomap Graph Network</h3>
</div>
</div>
<div id="Network2">
<div style="width: 50%; float:left; overflow: auto;"></div>
<div id="title_2">
<h3>Spectral Clustering on Isomap Graph Network</h3>
</div>
</div>
</div>
<div style="width: 50%; float:right; overflow: auto;">
<div id="Network3">
<div id="title_3">
<h3>Calculated Cohesive Energy</h3>
</div>
</div>
<div id="Network4">
<div id="title_4">
<h3>Similarity score against CaTiO3</h3>
</div>
</div>
</div>
</div>
</div>
<div style="width: 20%; height: 500px; float:right;">
<div id="HSA_fingerprint">
<div id="title">
<h3>Hirschfeld Surface Fingerprint Plot</h3>
</div>
</div>
</div>
还有一个小提琴链接:https://jsfiddle.net/shashank2104/bj76ckh4/4/
不过我有一些建议:
drawNetworkFunction
调用都会提取文件,这会减慢页面的呈现速度。 linkedByIndex
,该对象独立于描述符或chartId 。 建议:在单个函数中移动上述步骤,并将linkedByIndex
和graph
(数据)传递到drawNetworkFunction
,然后传递其余的。希望这会有所帮助。