Я пытаюсь изменить пример мобильных патентов, чтобы разрешить несколько ссылок в одном направлении.
У меня есть данные (да, я знаю, что Джим на самом деле не Pam boss):
source target relationship
Michael Scott Jan Levenson pro
Jan Levenson Michael Scott personal
Jim Halpert Pam Beasley pro
Jim Halpert Pam Beasley personal
Многоканальная функциональность примера Mobil Patents Suit позволяет правильно отображать первые две строки (две дуги). Однако для двух последних строк представлена только одна смешанная дуга.
Вопрос: Как разрешить ссылки с той же направленностью, которые будут показаны как несколько дуг, а не одна дуга?
Вот мой код дуги (разорванный прямо из примера мобильных патентов):
function tick() {
path.attr("d", linkArc);
circle.attr("transform", transform);
text.attr("transform", transform);
}
function linkArc(d) {
var dx = d.target.x - d.source.x,
dy = d.target.y - d.source.y,
dr = Math.sqrt(dx * dx + dy * dy);
return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
}
function transform(d) {
return "translate(" + d.x + "," + d.y + ")";
}
Любая помощь вообще была бы весьма признательна. Спасибо!
Вероятно, для этого существует несколько потенциальных подходов, один приходит на ум довольно быстро: используйте другой генератор путей для каждого отношения типов между узлами. У вас должно быть свойство, указывающее характер отношений (которые у вас есть в вашем вопросе), и используйте это, чтобы установить выравнивание по пути.
В нижеприведенном фрагменте я проверяю, какая связь рисуется, и уменьшаем радиус дуги в личных отношениях на 50% по сравнению с радиусом радиуса профессиональных отношений. Соответствующая часть:
function linkArc(d) {
var dx = d.target.x - d.source.x,
dy = d.target.y - d.source.y,
dr = Math.sqrt(dx * dx + dy * dy);
if(d.relationship == "pro") {
return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
}
else {
return "M" + d.source.x + "," + d.source.y + "A" + (dr * 0.3) + "," + (dr * 0.3) + " 0 0,1 " + d.target.x + "," + d.target.y;
}
}
Здесь все на практике:
var links = [
{ source: "Michael Scott",
target:"Jan Levenson",
relationship: "pro"
},
{ source:"Jan Levenson",
target:"Michael Scott",
relationship: "Personal"
},
{ source: "Jim Halpert",
target: "Pam Beasley",
relationship: "pro"
},
{
source: "Jim Halpert",
target: "Pam Beasley",
relationship: "Personal"
}
]
var nodes = {};
// 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});
});
var width = 960,
height = 500;
var force = d3.layout.force()
.nodes(d3.values(nodes))
.links(links)
.size([width, height])
.linkDistance(60)
.charge(-300)
.on("tick", tick)
.start();
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
// Per-type markers, as they don't inherit styles.
svg.append("defs").selectAll("marker")
.data(["suit", "licensing", "resolved"])
.enter().append("marker")
.attr("id", function(d) { return d; })
.attr("viewBox", "0 -5 10 10")
.attr("refX", 15)
.attr("refY", -1.5)
.attr("markerWidth", 6)
.attr("markerHeight", 6)
.attr("orient", "auto")
.append("path")
.attr("d", "M0,-5L10,0L0,5");
var path = svg.append("g").selectAll("path")
.data(force.links())
.enter().append("path")
.attr("class", function(d) { return "link " + d.type; })
.attr("marker-end", function(d) { return "url(#" + d.type + ")"; });
var circle = svg.append("g").selectAll("circle")
.data(force.nodes())
.enter().append("circle")
.attr("r", 6)
.call(force.drag);
var text = svg.append("g").selectAll("text")
.data(force.nodes())
.enter().append("text")
.attr("x", 8)
.attr("y", ".31em")
.text(function(d) { return d.name; });
// Use elliptical arc path segments to doubly-encode directionality.
function tick() {
path.attr("d", linkArc);
circle.attr("transform", transform);
text.attr("transform", transform);
}
function linkArc(d) {
var dx = d.target.x - d.source.x,
dy = d.target.y - d.source.y,
dr = Math.sqrt(dx * dx + dy * dy);
if(d.relationship == "pro") {
return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
}
else {
return "M" + d.source.x + "," + d.source.y + "A" + (dr * 0.3) + "," + (dr * 0.3) + " 0 0,1 " + d.target.x + "," + d.target.y;
}
}
function transform(d) {
return "translate(" + d.x + "," + d.y + ")";
}
.link {
fill: none;
stroke: #666;
stroke-width: 1.5px;
}
#licensing {
fill: green;
}
.link.licensing {
stroke: green;
}
.link.resolved {
stroke-dasharray: 0,2 1;
}
circle {
fill: #ccc;
stroke: #333;
stroke-width: 1.5px;
}
text {
font: 10px sans-serif;
pointer-events: none;
text-shadow: 0 1px 0 #fff, 1px 0 0 #fff, 0 -1px 0 #fff, -1px 0 0 #fff;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>