Д3.JS force layout-размещение/вращение метки края
Я довольно новый С D3.Джей-ЭС, а я тут играл с силовым макетом. Одной из вещей, которые я пробовал, было размещение ярлыков на ссылках.
один из способов сделать это путем добавления svg:text
и ручной расчет translate
& rotate
, который работает с прямыми линиями. Но, в случае, когда ссылка является svg:path
(например, arc), это работает не так, как ожидалось. В этих случаях svg:textPath
предложил решение.
на демо, вы можете увидеть простой реализация добавления меток к ссылкам через svg:textPath
. Единственная проблема заключается в том, что в случае, когда источник расположен справа от цели, текст отображается в противоположном направлении (с нашей точки зрения, он по-прежнему корректен с точки зрения пути). Мой вопрос в том, как с этим справиться?
только "решение" я придумал is, вручную меняя источник и цель в случае, описанном выше. здесь, вы можете видеть, что это почти строительство.
в состоянии, когда происходит своп, вы также можете увидеть, как дуга переворачивается на другую сторону, что выглядит неправильно. :(
1 ответов
@LarsKotthoff правильно, что textPath
должен следовать направлению пути. В этом случае направление пути определяет не только направление дуги, но и прикрепление маркера стрелки на конце - это усложняет обмен направлениями на лету, так как вам тоже придется перемещать маркер.
более простое решение (хотя, возможно, не лучшее, если у вас есть большое количество ссылок) - это "тень" реального пути ссылки с невидимым путем, используемым только для текст:
var link = svg.append("svg:g").selectAll("g.link")
.data(force.links())
.enter().append('g')
.attr('class', 'link');
var linkPath = link.append("svg:path")
.attr("class", function(d) { return "link " + d.type; })
.attr("marker-end", function(d) { return "url(#" + d.type + ")"; });
var textPath = link.append("svg:path")
.attr("id", function(d) { return d.source.index + "_" + d.target.index; })
.attr("class", "textpath");
теперь у вас есть отдельный путь вы можете правильно манипулировать. Как вы заметили, есть две проблемы-вы должны изменить направление пути, и вы должны изменить направление дуги. Похоже, вы можете сделать это в командной строке path, заменив sweep-flag
значение (см. docs), таким образом, вместо Arx,ry 0 0,1
вы Arx,ry 0 0,0
. Вы можете уменьшить дублирование кода, имея одну функцию для создания строк пути:
function arcPath(leftHand, d) {
var start = leftHand ? d.source : d.target,
end = leftHand ? d.target : d.source,
dx = end.x - start.x,
dy = end.y - start.y,
dr = Math.sqrt(dx * dx + dy * dy),
sweep = leftHand ? 0 : 1;
return "M" + start.x + "," + start.y + "A" + dr + "," + dr +
" 0 0," + sweep + " " + end.x + "," + end.y;
}
затем вы можете обновите путь ссылки и текстовый путь отдельно:
linkPath.attr("d", function(d) {
return arcPath(false, d);
});
textPath.attr("d", function(d) {
return arcPath(d.source.x < d.target.x, d);
});
см. рабочий код:http://jsfiddle.net/nrabinowitz/VYaGg/2/