我想在点击d3js中的任何节点时突出显示所选节点及其连接的节点, 其他节点将消失或变钝。
m[i,]
有没有办法在d3js中应用这种功能?
答案 0 :(得分:3)
有几种方法可以实现。这是其中之一:
circle.on("click", function(d) {
var thisNode = d.id
var connected = data.links.filter(function(e) {
return e.source === thisNode || e.target === thisNode
});
circle.attr("opacity", function(d) {
return (connected.map(d => d.source).indexOf(d.id) > -1 || connected.map(d => d.target).indexOf(d.id) > -1) ? 1 : 0.1
});
path.attr("opacity", function(d) {
return (d.source.id == thisNode || d.target.id == thisNode) ? 1 : 0.1
});
使用您的代码检查演示:
var color = d3.scale.category20();
//try{
// var data = JSON.parse(text);
//} catch (e) {
// window.alert("sometext: "+e);
//}
var data = {
"nodes": [{
"id": 127230,
"name": "Optimization of query evaluation algorithms",
"citation": 26,
"group": 10
}, {
"id": 127254,
"name": "Flow algorithms for parallel query optimization",
"citation": 22,
"group": 10
}, {
"id": 127380,
"name": "Randomized approximation algorithms for query optimization problems on two processors",
"citation": 14,
"group": 10
}, {
"id": 127438,
"name": "Optimization algorithms for simultaneous multidimensional queries in OLAP environments",
"citation": 12,
"group": 10
}, {
"id": 127063,
"name": "Query optimization in database systems",
"citation": 230,
"group": 10
}, {
"id": 127158,
"name": "Query optimization in a memory-resident domain relational calculus database system",
"citation": 41,
"group": 10
}, {
"id": 129760,
"name": "An Overview of TQuel",
"citation": 22,
"group": 10
}, {
"id": 129867,
"name": "ADVISORS",
"citation": 10,
"group": 10
}, {
"id": 129872,
"name": "Tellabs and THRIP through the Telkom Centre of Excellence at Rhodes University.",
"citation": 10,
"group": 10
}, {
"id": 127412,
"name": "Optimal service ordering in decentralized queries over web services",
"citation": 13,
"group": 10
}, {
"id": 130856,
"name": "Queries over Web Services",
"citation": 10,
"group": 10
}, {
"id": 130959,
"name": "Exploiting Parallelism to Accelerate Keyword Search On Deep-web Sources",
"citation": 10,
"group": 10
}, {
"id": 131199,
"name": "Contents lists available at ScienceDirect Future Generation Computer Systems",
"citation": 10,
"group": 10
}, {
"id": 131211,
"name": "Flow Algorithms for Parallel Query Optimization",
"citation": 10,
"group": 10
}, {
"id": 127373,
"name": "Multi-query Optimization for On-Line Analytical Processing",
"citation": 14,
"group": 10
}, {
"id": 133379,
"name": "Concise descriptions of subsets of structured sets",
"citation": 21,
"group": 10
}],
"links": [{
"source": 127230,
"target": 127063,
"name": "c1",
"value": 10,
"grouo": 1
}, {
"source": 127230,
"target": 127158,
"name": "c1",
"value": 10,
"grouo": 1
}, {
"source": 127230,
"target": 129760,
"name": "c1",
"value": 10,
"grouo": 1
}, {
"source": 127230,
"target": 129867,
"name": "c1",
"value": 10,
"grouo": 1
}, {
"source": 127230,
"target": 129872,
"name": "c1",
"value": 10,
"grouo": 1
}, {
"source": 127230,
"target": 127063,
"name": "c1",
"value": 10,
"grouo": 9
}, {
"source": 127230,
"target": 127158,
"name": "c1",
"value": 10,
"grouo": 9
}, {
"source": 127230,
"target": 129760,
"name": "c1",
"value": 10,
"grouo": 9
}, {
"source": 127230,
"target": 129867,
"name": "c1",
"value": 10,
"grouo": 9
}, {
"source": 127230,
"target": 129872,
"name": "c1",
"value": 10,
"grouo": 9
}, {
"source": 127254,
"target": 127412,
"name": "c1",
"value": 10,
"grouo": 1
}, {
"source": 127254,
"target": 130856,
"name": "c1",
"value": 10,
"grouo": 1
}, {
"source": 127254,
"target": 130959,
"name": "c1",
"value": 10,
"grouo": 1
}, {
"source": 127254,
"target": 131199,
"name": "c1",
"value": 10,
"grouo": 1
}, {
"source": 127254,
"target": 131211,
"name": "c1",
"value": 10,
"grouo": 1
}, {
"source": 127254,
"target": 127412,
"name": "c1",
"value": 10,
"grouo": 9
}, {
"source": 127254,
"target": 130856,
"name": "c1",
"value": 10,
"grouo": 9
}, {
"source": 127254,
"target": 130959,
"name": "c1",
"value": 10,
"grouo": 9
}, {
"source": 127254,
"target": 131199,
"name": "c1",
"value": 10,
"grouo": 9
}, {
"source": 127254,
"target": 131211,
"name": "c1",
"value": 10,
"grouo": 9
}, {
"source": 127438,
"target": 127373,
"name": "c1",
"value": 10,
"grouo": 1
}, {
"source": 127438,
"target": 133379,
"name": "c1",
"value": 10,
"grouo": 1
}, {
"source": 127438,
"target": 127373,
"name": "c1",
"value": 10,
"grouo": 9
}, {
"source": 127438,
"target": 133379,
"name": "c1",
"value": 10,
"grouo": 9
}]
};
// used to store the number of links between two nodes.
// mLinkNum[data.links[i].source + "," + data.links[i].target] = data.links[i].linkindex;
var mLinkNum = {};
// sort links first
// sortLinks();
data.links.sort(function(a, b) {
if (a.source > b.source) {
return 1;
} else if (a.source < b.source) {
return -1;
} else {
if (a.target > b.target) {
return 1;
}
if (a.target < b.target) {
return -1;
} else {
return 0;
}
}
})
// set up linkIndex and linkNumer, because it may possible multiple links share the same source and target node
setLinkIndexAndNum();
var w = 1345,
h = 1000;
var force = d3.layout.force()
.size([w, h])
.linkDistance(100)
.charge(-800)
.on("tick", tick);
var svg = d3.select("body").append("svg:svg")
.attr("width", w)
.attr("height", h);
var color = d3.scale.category10()
var edges = [];
data.links.forEach(function(e) {
var sourceNode = data.nodes.filter(function(n) {
return n.id === e.source;
})[0],
targetNode = data.nodes.filter(function(n) {
return n.id === e.target;
})[0];
edges.push({
source: sourceNode,
target: targetNode,
name: e.name,
value: e.value,
linkindex: e.linkindex,
grouo: e.grouo
});
});
force
.nodes(data.nodes)
.links(edges)
.start();
var path = svg.append("svg:g")
.selectAll("line")
.data(edges)
.enter().append("svg:path")
.attr("class", "link")
.style("stroke-width", function(d, i) {
return Math.sqrt(d.value);
}).style('stroke', function(d) {
return color(d.grouo);
});
var circle = svg.append("svg:g")
.selectAll("circle")
.data(force.nodes())
.enter().append("svg:circle")
.attr("r", function(d) {
return (Math.sqrt(d.citation));
})
.style("fill", function(d) {
return color(d.group);
})
.call(force.drag);
var text = svg.append("svg:g")
.selectAll("g")
.data(force.nodes())
.enter().append("svg:g");
// A copy of the text with a thick white stroke for legibility.
//text.append("svg:text")
//.attr("x", 8)
//.attr("y", ".31em")
//.attr("class", "shadow")
//.text(function (d) {
//return d.name;
//});
text.append("svg:text")
.attr("x", 8)
.attr("y", ".31em")
.text(function(d) {
// return d.name;
});
circle.on("click", function(d) {
var thisNode = d.id
var connected = data.links.filter(function(e) {
return e.source === thisNode || e.target === thisNode
});
circle.attr("opacity", function(d) {
return (connected.map(d => d.source).indexOf(d.id) > -1 || connected.map(d => d.target).indexOf(d.id) > -1) ? 1 : 0.1
});
path.attr("opacity", function(d) {
return (d.source.id == thisNode || d.target.id == thisNode) ? 1 : 0.1
});
})
// Use elliptical arc path segments to doubly-encode directionality.
function tick() {
path.attr("d", function(d, i) {
var dx = d.target.x - d.source.x,
dy = d.target.y - d.source.y,
dr = 30 * d.linkindex; //linknum is defined above
var output = "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
//console.log(d)
return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
});
// Add tooltip to the connection path
path.append("svg:title")
.text(function(d, i) {
return d.name;
});
circle.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
text.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
}
// sort the links by source, then target
function sortLinks1() {
data.links.sort(function(a, b) {
if (a.source > b.source) {
return 1;
} else if (a.source < b.source) {
return -1;
} else {
if (a.target > b.target) {
return 1;
}
if (a.target < b.target) {
return -1;
} else {
return 0;
}
}
});
}
//any links with duplicate source and target get an incremented 'linknum'
function setLinkIndexAndNum1() {
for (var i = 0; i < data.links.length; i++) {
if (i != 0 &&
data.links[i].source == data.links[i - 1].source &&
data.links[i].target == data.links[i - 1].target) {
data.links[i].linkindex = data.links[i - 1].linkindex + 1;
console.log(data.links[i].linkindex)
} else {
data.links[i].linkindex = 1;
}
// save the total number of links between two nodes
if (mLinkNum[data.links[i].target + "," + data.links[i].source] !== undefined) {
mLinkNum[data.links[i].target + "," + data.links[i].source] = data.links[i].linkindex;
} else {
mLinkNum[data.links[i].source + "," + data.links[i].target] = data.links[i].linkindex;
}
}
}
function setLinkIndexAndNum() {
for (var i = 0; i < data.links.length; i++) {
if (i != 0 &&
data.links[i].source == data.links[i - 1].source &&
data.links[i].target == data.links[i - 1].target) {
data.links[i].linkindex = data.links[i - 1].linkindex + 1;
} else {
data.links[i].linkindex = 1;
};
};
}
&#13;
path.link {
fill: none;
stroke: #666;
stroke-width: 1.5px;
}
circle {
fill: #ccc;
stroke: #333;
stroke-width: 1.5px;
}
text {
font: 10px sans-serif;
pointer-events: none;
}
text.shadow {
stroke: #fff;
stroke-width: 3px;
stroke-opacity: .8;
}
body {
background-color: white;
margin: 0px;
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
&#13;