我是d3(和javascript)的新手,这是我第一次在Stackoverflow上发布问题。如果我的问题不清楚或不合适,请告诉我。如果您提供任何建议或帮助,我将不胜感激。
我很难过滤力向图中的节点。我已经搜索并使用了其他问题(D3 force-directed graph - filter nodes and associated links)上发布的代码来隐藏节点及其关联的链接。但是,我无法隐藏所有链接都不可见的节点。
这就是我想要做的:
如果与该节点的所有链接都不可见,则该节点也应不可见。否则,如果可见与该节点相关的任何链接,则该节点应可见。我已经从jsfiddle.net(zhanghuancs / cuYu8 /)找到了这段代码,但是我无法在我的代码上使用此代码。(我无法在这里弄清楚如何链接jsfiddle代码。)
有人可以帮助我吗? 这是我的代码:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Force Layout</title>
<script type="text/javascript" src="http://code.jquery.com/jquery-2.1.0.js"></script>
<script type="text/javascript" src="http://code.jquery.com/ui/1.11.0/jquery-ui.min.js"></script>
<link rel="stylesheet" type="text/css" href="http://code.jquery.com/ui/1.11.0/themes/smoothness/jquery-ui.css">
<script type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script>
<script type="text/javascript" src="https://labratrevenge.com/d3-tip/javascripts/d3.tip.v0.6.3.js"></script>
<style id="compiled-css" type="text/css">
.node {
stroke: #fff;
stroke-width: 0.5px;
}
.link {
stroke: #999;
stroke-opacity: .1;
}
d3-tip {
line-height: 1;
color: black;
}
div {
display: inline-block;
}
form {
display: inline-block;
}
svg {
border: solid 1px blue;
}
body,
.container {
background-color: white;
margin: 5px;
}
.graphContainer {
text-shadow: -1px -1px 0 white, 1px -1px 0 white, -1px 1px 0 white, 1px 1px 0 white;
}
#sidebar{
position: absolute;
z-index: 2;
background-color: #FFF;
padding: 10px;
margin: 5px;
border: 1px solid #6895b4;
min-height: 3px;
width: 100px;
top:45px;
right:220px;
}
.item-group {
margin-bottom: 5px;
}
.item-group .item-label {
width: 90px;
text-align: right;
font-family: Arial,sans-serif;
font-size: 14px;
font-weight: bold;
position: relative;
min-height: 1px;
margin-top: 5px;
display: inline;
padding-right: 5px;
font-size: .90em;
}
.checkbox-interaction-group {
margin-left: 10px;
margin-top: 5px;
clear: both;
}
.checkbox-container {
display: block;
min-height: 30px;
vertical-align: middle;
margin-left: 10px;
}
.checkbox-container label{
display:inline;
margin-bottom: 0px;
}
</style>
</head>
<body>
<div id="container" class="container">
<div id="sidebar" style="display: none;">
<div class="item-group">
<label class="item-label">Filter</label>
<div id="filterContainer" class="filterContainer checkbox-interaction-group"></div>
</div>
</div>
<div id="graphContainer" class="graphContainer">
<script type="application/json" id="patent">
{
"nodes":[
{"label": "label1","title":"label1","group": "group1", "type": "label1", "s":1},
{"label": "label2","title":"label2","group": "group1", "type": "label2","s":1},
{"label": "label3","title":"label3","group": "group1", "type": "label3","s":1},
{"id":"5712454", "title": "title1", "group": "group2", "s":0},
{"id":"5497941", "title": "title2", "group": "group2", "s":0},
{"id":"5517952", "title": "title3", "group": "group2", "s":0},
{"id":"4854277", "title": "title4", "group": "group2", "s":0},
{"id":"9556782", "title": "title5", "group": "group2", "s":0}
],
"links":[
{"source": 3, "target": 0, "value": 1},
{"source": 3, "target": 1, "value": 1},
{"source": 3, "target": 2, "value": 1},
{"source": 4, "target": 0, "value": 1},
{"source": 5, "target": 2, "value": 1},
{"source": 6, "target": 1, "value": 1},
{"source": 7, "target": 2, "value": 1},
{"source": 7, "target": 0, "value": 1},
{"source": 6, "target": 2, "value": 1},
{"source": 5, "target": 1, "value": 1}
]
}
</script>
<!-- TODO: Missing CoffeeScript 2 -->
<script type="text/javascript">
//Constants for the SVG
var width = window.innerWidth,
height = window.innerHeight-47;
//Set up the colour scale
var color = d3.scale.category10();
//Set up the force layout
var force = d3.layout.force()
.charge(-200)
.linkDistance(20)
.size([width, height]);
// Set up zoom behavior
var zoom = d3.behavior.zoom().scaleExtent([0.1,5]).on("zoom",redraw);
//Append a SVG to the body of the html page. Assign this SVG as an object to svg
var svg = d3.select("body")
.append("svg")
.attr("width", width-240)
.attr("height", height)
.call(zoom)
.on("dblclick.zoom",null)
.append('g');
var svg2 = d3.select("body")
.append("svg")
.attr("width", 200)
.attr("height", height);
//Set up tooltip
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function (d) {
return d.title + "</span>";
})
svg.call(tip);
//Read the data from the mis element
var patent = document.getElementById('patent').innerHTML;
graph = JSON.parse(patent);
//Creates the graph data structure out of the json data
force.nodes(graph.nodes)
.links(graph.links)
.start()
.friction(0.5);
//Create all the line svgs but without locations yet
var link = svg.selectAll(".link")
.data(graph.links)
.enter().append("line")
.attr("class", "link")
.style("stroke-width", function (d) {return Math.sqrt(d.value);
});
//Do the same with the circles for the nodes - no
var node = svg.selectAll(".node")
.data(graph.nodes)
.enter().append("path")
.attr("class", "node")
.attr("d", d3.svg.symbol()
.type(function(d) { return d3.svg.symbolTypes[d.s]; }))
.style("fill", function (d) {return color(d.group);})
.call(force.drag)
.on('dblclick', connectedNodes)
.on('mouseover', tip.show)
.on('mouseout', tip.hide)
.on("click", function(d){
if (d3.event.shiftKey) {
var url = "https://patents.google.com/patent/US"+ d.id
alert("Redirecting you to " + url)
window.open(url,"", "width=800,height=800");
}
});
var label = svg.selectAll(".mytext")
.data(graph.nodes)
.enter()
.append("text")
.text(function (d) { return d.label; })
.style("text-anchor", "middle")
.style("fill","gray")
.style("font-family", "Arial")
.style("font-size", 8);
//Zoom and Pan function
function redraw() {
svg.attr("transform",
"translate(" + d3.event.translate + ")"
+ " scale(" + d3.event.scale + ")");
}
var drag = force.drag()
.on("dragstart", function(d) {
d3.event.sourceEvent.stopPropagation();
});
//Now we are giving the SVGs co-ordinates - the force layout is generating the co-ordinates which this code is using to update the attributes of the SVG elements
force.on("tick", function () {
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("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
label.attr("x", function(d){ return d.x; })
.attr("y", function (d) {return d.y - 10; });
});
//Highlight function
//Toggle stores whether the highlighting is on
var toggle = 0;
//Create an array logging what is connected to what
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;
});
//This function looks up whether a pair are neighbours
function neighboring(a, b) {
return linkedByIndex[a.index + "," + b.index];
}
function connectedNodes() {
if (toggle == 0) {
//Reduce the opacity of all but the neighbouring nodes
d = d3.select(this).node().__data__;
node.style("opacity", function (o) {
return neighboring(d, o) | neighboring(o, d) ? 1 : 0.1;
});
label.style("opacity", function (o) {
return neighboring(d, o) | neighboring(o, d) ? 1 : 0.1;
});
link.style("opacity", function (o) {
return d.index==o.source.index | d.index==o.target.index ? 1 : 0.1;
});
//Reduce the op
toggle = 1;
} else {
//Put them back to opacity=1
node.style("opacity", 1);
link.style("opacity", 1);
label.style("opacity",1);
toggle = 0;
}
}
//Search function
var optArray = [];
for (var i = 0; i < graph.nodes.length; i++) {
optArray.push(graph.nodes[i].title);
}
optArray = optArray.sort();
$(function () {
$("#search").autocomplete({
source: optArray
});
});
window.searchNode = searchNode;
function searchNode() {
//find the node
var selectedVal = document.getElementById('search').value;
if (selectedVal == "none") {
node.style("stroke", "white").style("stroke-width", "1");
} else {
var selected = node.filter(function (d, i) {
return d.title != selectedVal;
});
selected.style("opacity", "0");
link.style("opacity", "0");
label.style("opacity", "0");
d3.selectAll(".node, .link").transition()
.duration(2000)
.style("opacity", 1);
label.transition()
.duration(2000)
.style("opacity",1);
var selectedNode = node
.filter(function (d, i) { return d.title == selectedVal; })
.datum();
var scale = zoom.scale();
var desiredPosition = { x: (width-240)/2, y: height/2}; // constants, set to svg center point
zoom.translate([desiredPosition.x - selectedNode.x*scale, desiredPosition.y - selectedNode.y*scale]);
zoom.event(svg);
}
}
//Legend
var legend = svg2.selectAll(".legend")
.data(color.domain())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
legend.append("rect")
.attr("x", 5)
.attr("y",5)
.attr("width", 18)
.attr("height", 18)
.style("fill", color);
legend.append("text")
.attr("x", 30)
.attr("y", 13)
.attr("dy", ".35em")
.style("text-anchor", "start")
.text(function(d) { return d });
// call method to create filter
createFilter();
// method to create filter
function createFilter(){
d3.select(".filterContainer").selectAll("div")
.data(["label1","label2","label3"])
.enter()
.append("div")
.attr("class", "checkbox-container")
.append("label")
.each(function(d) {
// create checkbox for each data
d3.select(this).append("input")
.attr("type", "checkbox")
.attr("id", function(d) {return "chk_" + d;})
.attr("checked", true)
.on("click", function(d, i) {
// register on click event
var lVisibility = this.checked? "visible":"hidden";
filterGraph(d, lVisibility);
})
d3.select(this).append("span")
.text(function(d){return d;});
});
$("#sidebar").show(); // show sidebar
}
var hidden_nodes =[];
// Method to filter graph
function filterGraph(aType, aVisibility){
// change the visibility of the node
// if all the links with that node are invisibile, the node should also be invisible
// otherwise if any link related to that node is visibile, the node should be visible
// change the visibility of the connection link
node.style("visibility", function(o) {
var lOriginalVisibility = $(this).css("visibility");
if (o.type == aType) {
if (aVisibility == "hidden")
{
hidden_nodes.push(o.title);
}
else
{
index = hidden_nodes.indexOf(o.title);
if (index > -1)
{
hidden_nodes.splice(index, 1);
}
}
}
return o.type === aType ? aVisibility : lOriginalVisibility;
});
label.style("visibility", function(o) {
var lOriginalVisibility = $(this).css("visibility");
if (o.type == aType) {
if (aVisibility == "hidden")
{
hidden_nodes.push(o.title);
}
else
{
index = hidden_nodes.indexOf(o.title);
if (index > -1)
{
hidden_nodes.splice(index, 1);
}
}
}
return o.type === aType ? aVisibility : lOriginalVisibility;
});
link.attr("display", function (o) {
////Here the structure of the the link can vary, sometimes it is o["source"]["name"], sometimes it is o["source"]["name"], check it out before you fill in.
var source_name = o["source"]["title"];
var target_name = o["target"]["title"];
var result = hidden_nodes.indexOf(source_name) != -1 || hidden_nodes.indexOf(target_name) != -1 ? "none" : "auto"
return result;
})
;
}
</script>
</div>
</body>
</html>