Этикетки не показаны
Я пытаюсь реализовать помеченные ребра на силовом ориентированном графе.
Пример, который я использую, можно найти здесь.
Соответствующие биты кода в примере приведены здесь.
Мой код следующий:
<style>
.node {
stroke: #fff;
stroke-width: 0.5px;
}
.node text {
pointer-events: none;
font: 15px helvetica;
}
.link {
fill: none;
stroke: #bbb;
stroke-width: 3.0px;
opacity: 0.5;
}
.highlight {
stroke: #259359;
}
</style>
<body>
<script src= "//d3js.org/d3.v3.min.js" > </script>
<script>
var width = 700,
height = 550;
var color = d3.scale.category20();
var force = d3.layout.force()
.linkStrength(1)
.distance(0.01)
.gravity(0.2)
.charge(-500)
.size([width, height]);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
svg.append("defs").selectAll("marker")
.data(["end"]) // Different link/path types can be defined here
.enter().append("marker") // This section adds in the arrows
.attr("id", String)
.attr("viewBox", "0 -5 10 10")
.attr("refX", 16)
.attr("refY", 0)
.attr("markerWidth", 3)
.attr("markerHeight", 3)
.attr("orient", "auto")
.append("path")
.attr("d", "M0,-5L10,0L0,5")
.style("stroke", "#bbb");
d3.json("fg.json", function(error, graph) {
if (error) throw error;
var nodes = graph.nodes.slice(),
links = [],
bilinks = [];
graph.links.forEach(function(link) {
var s = nodes[link.source],
t = nodes[link.target],
i = {}; // intermediate node
nodes.push(i);
links.push({
source: s,
target: i
}, {
source: i,
target: t
});
bilinks.push([s, i, t]);
});
force
.nodes(nodes)
.links(links)
.size([width, height])
.start();
var link = svg.selectAll(".link")
.data(bilinks)
.enter().append("path")
.attr("class", "link")
.style("marker-end", "url(#end)")
.on("mouseover", function() {
d3.select(d3.event.target).classed("highlight", true);
})
.on("mouseout", function() {
d3.select(d3.event.target).classed("highlight", false);
});
var node = svg.selectAll(".node")
.data(graph.nodes)
.enter().append("g")
.attr("class", "node")
.call(force.drag)
node.append("circle")
.attr("r", 8)
.style("fill", function(d) {
return color(d.group);
})
node.append("text")
.attr("dx", 15)
.attr("dy", ".40em")
.text(function(d) {
return d.name
})
.style("stroke", "gray");
//
var padding = 30, // separation between circles
radius = 1;
function collide(alpha) {
var quadtree = d3.geom.quadtree(graph.nodes);
return function(d) {
var rb = 2 * radius + padding,
nx1 = d.x - rb,
nx2 = d.x + rb,
ny1 = d.y - rb,
ny2 = d.y + rb;
quadtree.visit(function(quad, x1, y1, x2, y2) {
if (quad.point && (quad.point !== d)) {
var x = d.x - quad.point.x,
y = d.y - quad.point.y,
l = Math.sqrt(x * x + y * y);
if (l < rb) {
l = (l - rb) / l * alpha;
d.x -= x *= l;
d.y -= y *= l;
quad.point.x += x;
quad.point.y += y;
}
}
return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1;
});
};
}
var edgepaths = svg.selectAll(".edgepath")
.data(graph.links)
.enter()
.append('path')
.attr({'d': function(d) {return 'M '+d.source.x+' '+d.source.y+' L '+ d.target.x +' '+d.target.y},
'class':'edgepath',
'fill-opacity':0,
'stroke-opacity':0,
'fill':'blue',
'stroke':'red',
'id':function(d,i) {return 'edgepath'+i}})
.style("pointer-events", "none");
var edgelabels = svg.selectAll(".edgelabel")
.data(graph.links)
.enter()
.append('text')
.style("pointer-events", "none")
.attr({'class':'edgelabel',
'id':function(d,i){return 'edgelabel'+i},
'dx':80,
'dy':0,
'font-size':10,
'fill':'#aaa'});
edgelabels.append('textPath')
.attr('xlink:href',function(d,i) {return '#edgepath'+i})
.style("pointer-events", "none")
.text(function(d,i){return 'label '+i});
force.on("tick", function() {
link.attr("d", function(d) {
return "M" + d[0].x + "," + d[0].y + "S" + d[1].x + "," + d[1].y + " " + d[2].x + "," + d[2].y;
});
node.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
edgepaths.attr('d', function(d) { var path='M '+d.source.x+' '+d.source.y+' L '+ d.target.x +' '+d.target.y;
return path});
edgelabels.attr('transform',function(d,i){
if (d.target.x<d.source.x){
bbox = this.getBBox();
rx = bbox.x+bbox.width/2;
ry = bbox.y+bbox.height/2;
return 'rotate(180 '+rx+' '+ry+')';
}
else {
return 'rotate(0)';
}
});
node.each(collide(0.5));
});
});
</script>
Данные приведены ниже:
{
"nodes":[
{"name":"alkene","group":1},
{"name":"alkane","group":1},
{"name":"halogenoalkane","group":2},
{"name":"dihalogenoalkane","group":2},
{"name":"amine","group":3},
{"name":"alcohol","group":4},
{"name":"ketone","group":5},
{"name":"aldehyde","group":6},
{"name":"hydroxynitrile","group":7},
{"name":"ester","group":8},
{"name":"carboxylic acid","group":9},
{"name":"acyl chloride","group":9},
{"name":"amide","group":10},
{"name":"nitrile","group":11}
],
"links":[
{"source":0,"target":2,"value":2},
{"source":0,"target":1,"value":1},
{"source":2,"target":0,"value":8},
{"source":0,"target":3,"value":10},
{"source":2,"target":4,"value":10},
{"source":5,"target":2,"value":1},
{"source":2,"target":5,"value":1},
{"source":6,"target":5,"value":1},
{"source":5,"target":6,"value":1},
{"source":7,"target":5,"value":1},
{"source":5,"target":7,"value":1},
{"source":7,"target":8,"value":2},
{"source":7,"target":10,"value":1},
{"source":10,"target":7,"value":1},
{"source":5,"target":9,"value":3},
{"source":10,"target":9,"value":3},
{"source":13,"target":10,"value":5},
{"source":10,"target":11,"value":1},
{"source":11,"target":10,"value":1},
{"source":11,"target":12,"value":1}
]
}
К сожалению, метки на графике не видны.
Конечная цель - показать соответствующее значение "значение" на каждом ребре.
Не могли бы вы сказать мне, что я делаю не так?
Спасибо за ваше время.
ОБНОВИТЬ
Метки были успешно добавлены к краям путем замены
"M" + d[0].x + "," + d[0].y + "S" + d[1].x + "," + d[1].y + " " + d[2].x + "," + d[2].y
за
'M '+d.source.x+' '+d.source.y+' L '+ d.target.x +' '+d.target.y
Однако остается вопрос: как можно добавить данные "value" вместо меток "label i"? Кроме того, как можно реализовать их появление при наведении мыши?
ОБНОВЛЕНИЕ II
Элемент "value" был создан для показа путем определения.data(graph.links) для textPath для edgelabels и затем возврата значения d.value. Подскажите, пожалуйста, как можно навести курсор мыши? Было бы хорошо, если бы значение "value" каждого ребра было видно только при наведении. Спасибо!
1 ответ
Из этого примера: http://jsfiddle.net/7HZcR/3/
Я создал то же представление, но с вашими данными здесь: http://jsfiddle.net/thatOneGuy/7HZcR/515/
Так что вам нужно реализовать стрелки.
То, что вы имели ранее, вы не могли войти в данные mouseover
поскольку данные, которые вы принесли, не содержат их.
Итак, в этом я привел данные так:
var links = graph.links;
Установите его для своих данных, но так как он имеет только индексы в качестве источника и цели, вам нужно присоединить узлы к источнику и цели, чтобы он правильно целился:
// Compute the distinct nodes from the links.
links.forEach(function(link) {
link.source = nodes[link.source] || (nodes[link.source] = {name: link.source});
link.target = nodes[link.target] || (nodes[link.target] = {name: link.target});
});
Теперь возвращаемые данные будут иметь вид:
{
source : someNode,
target : someNode,
value : linkValue
}
Итак, я создал текстовый вывод, чтобы определить, куда поместить значение в ссылку, будет сложно, так как вам нужно разработать кривую и т. Д.:
var textOutput = svg.append('text').attr('class', 'textOutput')
.attr("transform","translate(50, 100)");
Скоро mouseover
установить textOutput:
.on('mouseover', function(d){
console.log(d);
d3.select(this).style('stroke', 'red').style('stroke-width', '5')
textOutput.text('LINK VALUE : ' + d.value);
})
.on('mouseout', function(d){
d3.select(this).style('stroke', '#666') .style('stroke-width', '1')
});
Надеюсь, это поможет:)