Как добавить составной узел в силовой макет D3? - PullRequest
7 голосов
/ 09 февраля 2012

Я добавляю узлы к графу раскладки сил следующим образом:

var node = vis.selectAll("circle.node")
    .data(nodes)
    .enter()
    .append("circle")
    .attr("class", "node")
    .attr("cx", function(d) { return d.x; })
    .attr("cy", function(d) { return d.y; })
    .attr("r", 5)
    .style("fill", function(d) { return fill(d.group); })
    .call(force.drag);

Есть ли способ добавить составные элементы SVG как узлы?Т.е. я хочу добавить гиперссылку для каждого круга, поэтому мне нужно что-то вроде этого:

<a href="whatever.com"><circle ...></circle></a>

Ответы [ 2 ]

32 голосов
/ 11 февраля 2012

Создать «составной» элемент так же просто, как добавить одного или нескольких дочерних элементов к другому элементу. В вашем примере вы хотите связать свои данные с набором <a> элементов и дать каждому <a> одного <circle> дочернего элемента.

Прежде всего, вам нужно выбрать "a.node" вместо "circle.node". Это потому, что ваши гиперссылки будут родительскими элементами. Если нет очевидного родительского элемента, и вы просто хотите добавить несколько элементов для каждого элемента данных, используйте <g>, элемент группы SVG.

Затем вы хотите добавить один элемент <a> к каждому узлу во входящей выборке. Это создает ваши гиперссылки. После установки атрибутов каждой гиперссылки, вы хотите дать ей <circle> дочерний элемент. Просто: просто позвоните .append("circle").

var node = vis.selectAll("a.node")
    .data(nodes);

// The entering selection: create the new <a> elements here.
// These elements are automatically part of the update selection in "node".
var nodeEnter = node.enter().append("a")
    .attr("class", "node")
    .attr("xlink:href", "http://whatever.com")
    .call(force.drag);

// Appends a new <circle> element to each element in nodeEnter.
nodeEnter.append("circle")
    .attr("r", 5)
    .style("fill", function(d) { return fill(d.group); })

node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });

Помните, что D3 в основном работает на выборках узлов. Таким образом, вызов .append() для ввода selection означает, что каждый узел в выборе получает нового дочернего элемента. Мощные вещи!

Еще одна вещь: SVG имеет свой собственный <a> элемент , о котором я говорил выше. Это отличается от HTML! Как правило, элементы SVG используются только с SVG, а HTML - с HTML.

Спасибо @mbostock за предложение разъяснить имя переменной.

10 голосов
/ 11 февраля 2012

Ответ Джейсону Дэвису (поскольку stackoverflow ограничивает длину комментариев к комментариям…): Отличный ответ. Будьте осторожны с цепочкой метода; обычно вы хотите, чтобы node ссылался на внешний элемент привязки, а не на элемент внутренней окружности. Поэтому я бы порекомендовал небольшой вариант:

var node = vis.selectAll("a.node")
    .data(nodes)
  .enter().append("a")
    .attr("class", "node")
    .attr("xlink:href", "http://whatever.com")
    .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; })
    .call(force.drag);

node.append("circle")
    .attr("r", 5)
    .style("fill", function(d) { return fill(d.group); });

Я также заменил атрибуты cx и cy круга на преобразование на содержащем элемент привязки; либо один будет работать. Вы можете рассматривать элементы svg: a как svg: g (оба являются контейнерами), что хорошо, если вы хотите добавить метки позже.

...