javascript d3js 强制定向 - 在悬停到节点时,突出显示/着色链接的节点和链接?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19111581/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
d3js force directed - On hover to node, highlight/colourup linked nodes and links?
提问by dzordz
I have force directed graph with 4 types of nodes and two types of links. One type of node (the small blue one) I'm using as "connection node" between two bigger nodes.
我有 4 种类型的节点和两种类型的链接的力有向图。我用作两个较大节点之间的“连接节点”的一种节点(蓝色小节点)。
on mouseover node, it gets bigger, but also I wanna colour up "connections" to this node in different color. So whey you hover over a node... all links and little "connection nodes" gets in the different color, so you can know to which other bigger node is this one hovered connected.
在鼠标悬停节点上,它变得更大,但我也想用不同的颜色为这个节点的“连接”着色。所以当你将鼠标悬停在一个节点上时......所有链接和小“连接节点”都以不同的颜色显示,所以你可以知道这个悬停连接到哪个更大的节点。
You can see my situation on following link: http://jsfiddle.net/2pdxz/
您可以在以下链接中查看我的情况:http: //jsfiddle.net/2pdxz/
For example: If you hover up Google
node, links to Yahoo
with "connection" node gets highlighted and links to CDO
and CTO
gets highlighted
例如:如果您将鼠标悬停在Google
节点上,则Yahoo
与“连接”节点的链接将突出显示,而链接到CDO
并CTO
突出显示
I've tried to add this part of code:
我试图添加这部分代码:
function fade(opacity)
{ link.style("opacity", function(d) {
return d.source === d || d.target === d ? 1 : opacity;
});
}
which I picked up from some other question with the similar problem but I don't know how this could actually help me, because I'm noob about d3js.
这是我从其他一些有类似问题的问题中学到的,但我不知道这实际上对我有什么帮助,因为我对 d3js 一窍不通。
The exact code looks like this
确切的代码看起来像这样
Script:
脚本:
var data = {"nodes":[
{"name":"YHO", "full_name":"Yahoo", "type":1, "slug": "www.yahoo.com", "entity":"company", "img_hrefD":"", "img_hrefL":""},
{"name":"GGL", "full_name":"Google", "type":2, "slug": "www.google.com", "entity":"company", "img_hrefD":"", "img_hrefL":""},
{"name":"BNG", "full_name":"Bing", "type":2, "slug": "www.bing.com", "entity":"company", "img_hrefD":"", "img_hrefL":""},
{"name":"YDX", "full_name":"Yandex", "type":2, "slug": "www.yandex.com", "entity":"company", "img_hrefD":"", "img_hrefL":""},
{"name":"Desc1", "type":4, "slug": "", "entity":"description"},
{"name":"Desc2", "type":4, "slug": "", "entity":"description"},
{"name":"Desc4", "type":4, "slug": "", "entity":"description"},
{"name":"CEO", "prefix":"Mr.", "fst_name":"Jim", "snd_name":"Bean", "type":3, "slug": "", "entity":"employee"},
{"name":"ATT", "prefix":"Ms.", "fst_name":"Jenna", "snd_name":"Jameson", "type":3, "slug": "", "entity":"employee"},
{"name":"CTO", "prefix":"Mr.", "fst_name":"Lucky", "snd_name":"Luke", "type":3, "slug": "", "entity":"employee"},
{"name":"CDO", "prefix":"Ms.", "fst_name":"Pamela", "snd_name":"Anderson", "type":3, "slug": "", "entity":"employee"},
{"name":"CEO", "prefix":"Mr.", "fst_name":"Nacho", "snd_name":"Vidal", "type":3, "slug": "", "entity":"employee"},
],
"links":[
{"source":0,"target":4,"value":1,"distance":5},
{"source":0,"target":5,"value":1,"distance":5},
{"source":0,"target":6,"value":1,"distance":5},
{"source":1,"target":4,"value":1,"distance":5},
{"source":2,"target":5,"value":1,"distance":5},
{"source":3,"target":6,"value":1,"distance":5},
{"source":7,"target":3,"value":10,"distance":6},
{"source":8,"target":3,"value":10,"distance":6},
{"source":9,"target":1,"value":10,"distance":6},
{"source":10,"target":1,"value":10,"distance":6},
{"source":11,"target":2,"value":10,"distance":6},
]
}
var w = 560,
h = 500,
radius = d3.scale.log().domain([0, 312000]).range(["10", "50"]);
var vis = d3.select("body").append("svg:svg")
.attr("width", w)
.attr("height", h);
//vis.append("defs").append("marker")
//.attr("id", "arrowhead")
//.attr("refX", 22 + 3) /*must be smarter way to calculate shift*/
//.attr("refY", 2)
//.attr("markerWidth", 6)
//.attr("markerHeight", 4)
//.attr("orient", "auto")
//.append("path")
//.attr("d", "M 0,0 V 4 L6,2 Z"); //this is actual shape for arrowhead
//d3.json(data, function(json) {
var force = self.force = d3.layout.force()
.nodes(data.nodes)
.links(data.links)
.linkDistance(function(d) { return (d.distance*10); })
//.friction(0.5)
.charge(-250)
.size([w, h])
.start();
var link = vis.selectAll("line.link")
.data(data.links)
.enter().append("svg:line")
.attr("class", function (d) { return "link" + d.value +""; })
.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; })
.attr("marker-end", function(d) {
if (d.value == 1) {return "url(#arrowhead)"}
else { return " " }
;});
function fade(opacity) {
link.style("opacity", function(d) {
return d.source === d || d.target === d ? 1 : opacity;
});
}
function openLink() {
return function(d) {
var url = "";
if(d.slug != "") {
url = d.slug
} //else if(d.type == 2) {
//url = "clients/" + d.slug
//} else if(d.type == 3) {
//url = "agencies/" + d.slug
//}
window.open("//"+url)
}
}
var node = vis.selectAll("g.node")
.data(data.nodes)
.enter().append("svg:g")
.attr("class", "node")
.call(force.drag);
node.append("circle")
.attr("class", function(d){ return "node type"+d.type})
.attr("r",function(d){if(d.entity == "description"){ return 6 } else { return 18 }})
//.on("mouseover", expandNode);
//.style("fill", function(d) { return fill(d.type); })
node.append("svg:image")
.attr("class", function(d){ return "circle img_"+d.name })
.attr("xlink:href", function(d){ return d.img_hrefD})
.attr("x", "-36px")
.attr("y", "-36px")
.attr("width", "70px")
.attr("height", "70px")
.on("click", openLink())
.on("mouseover", function (d) { if(d.entity == "company")
{
d3.select(this).attr("width", "90px")
.attr("x", "-46px")
.attr("y", "-36.5px")
.attr("xlink:href", function(d){ return d.img_hrefL});
}
})
.on("mouseout", function (d) { if(d.entity == "company")
{
d3.select(this).attr("width", "70px")
.attr("x", "-36px")
.attr("y", "-36px")
.attr("xlink:href", function(d){ return d.img_hrefD});
}
});
node.append("text")
.attr("class", function(d){ return "nodetext title_"+d.name })
.attr("dx", 0)
.attr("dy", ".35em")
.style("font-size","10px")
.attr("text-anchor", "middle")
.style("fill", "white")
.text(function(d) { if (d.entity != "description"){return d.name} });
node.on("mouseover", function (d) {
if (d.entity == "company"){
d3.select(this).select('text')
.transition()
.duration(300)
.text(function(d){
return d.full_name;
})
.style("font-size","15px")
}
else if(d.entity == "employee"){
var asdf = d3.select(this);
asdf.select('text').remove();
asdf.append("text")
.text(function(d){return d.prefix + ' ' + d.fst_name })
.attr("class","nodetext")
.attr("dx", 0)
.attr("dy", ".35em")
.style("font-size","5px")
.attr("text-anchor", "middle")
.style("fill", "white")
.transition()
.duration(300)
.style("font-size","12px");
asdf.append("text").text(function(d){return d.snd_name })
.attr("class","nodetext")
.attr("transform","translate(0, 12)")
.attr("dx", 0)
.attr("dy", ".35em")
.style("font-size","5px")
.attr("text-anchor", "middle")
.style("fill", "white")
.transition()
.duration(300)
.style("font-size","12px");
}
else {
d3.select(this).select('text')
.transition()
.duration(300)
.style("font-size","15px")
}
if (d.entity == "company") {
d3.select(this).select('image')
.attr("width", "90px")
.attr("x", "-46px")
.attr("y", "-36.5px")
.attr("xlink:href", function (d) {
return d.img_hrefL
});
}
if (d.entity == "company") {
d3.select(this).select('circle')
.transition()
.duration(300)
.attr("r",28)
}
else if (d.entity == "employee"){
d3.select(this).select('circle')
.transition()
.duration(300)
.attr("r",32)
}
})
node.on("mouseout", function (d) {
if (d.entity == "company") {
d3.select(this).select('text')
.transition()
.duration(300)
.text(function(d){return d.name;})
.style("font-size","10px")
}
else if(d.entity == "employee"){
///////////////////////////
// CHANGE
///////////////////////////
d3.select(this).selectAll('text').remove();
//d3.select(this).select('text')
d3.select(this).append('text')
.text(function(d){return d.name;})
.style("font-size","14px")
.attr("dx", 0)
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.style("fill", "white")
.attr("class","nodetext")
.transition()
.duration(300)
.style("font-size","10px")
}
else {
d3.select(this).select('text')
.transition()
.duration(300)
.style("font-size","10px")
}
if (d.entity == "company") {
d3.select(this).select('image')
.attr("width", "70px")
.attr("x", "-36px")
.attr("y", "-36px")
.attr("xlink:href", function (d) {
return d.img_hrefD
});
}
if (d.entity == "company" || d.entity == "employee") {
d3.select(this).select('circle')
.transition()
.duration(300)
.attr("r",18)
}
});
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 + ")"; });
});
//});
CSS:
CSS:
@charset "utf-8";
/* CSS Document */
.link10 { stroke: #ccc; stroke-width: 2px; stroke-dasharray: 3, 3; }
.link1 { stroke: #000; stroke-width: 2px;}
.nodetext { pointer-events: none;}
.node.type1 {
fill:#690011;
}
.node.type2 {
fill:#BF0426;
}
.node.type3 {
fill:#E5B96F;
}
.node.type4 {
fill:#FFFFFF;
stroke:#1695A3;
stroke-width: 3px;
}
.node.type5 {
fill:#1BC9E0;
}
.node.type6 {
fill:#E01B98;
}
image.circle {
cursor:pointer;
}
.fadein{
display:none;
font-size:20px;
}
.rectD{
background-color:#000000;
width:70px;
height:30px
}
.rectL{
background-color:#000000;
width:90px;
height:30px
}
You can edit and see working example in my linked jsfiddle..
您可以在我链接的 jsfiddle 中编辑和查看工作示例。
Any suggestion or help is welcome..
欢迎任何建议或帮助..
回答by t.888
The way I solved this problem in my own project was to examine the links to see if their source or target properties matched the hovered node. This should be a step in the right direction.
我在自己的项目中解决这个问题的方法是检查链接以查看它们的源或目标属性是否与悬停的节点匹配。这应该是朝着正确方向迈出的一步。
// On node hover, examine the links to see if their
// source or target properties match the hovered node.
node.on('mouseover', function(d) {
link.style('stroke-width', function(l) {
if (d === l.source || d === l.target)
return 4;
else
return 2;
});
});
// Set the stroke width back to normal when mouse leaves the node.
node.on('mouseout', function() {
link.style('stroke-width', 2);
});
Updated fiddle: http://jsfiddle.net/2pdxz/2/
更新小提琴:http: //jsfiddle.net/2pdxz/2/