Выделите выбранный узел, его связи и его дочерние элементы в графе, ориентированном на силу D3


Я работаю над силовым ориентированным графом в D3. Я хочу выделить узел наведения курсора мыши, его ссылки и его дочерние узлы, установив все другие узлы и ссылки на более низкую непрозрачность.

в этом примере,http://jsfiddle.net/xReHA/, я могу исчезать все ссылки и узлы, а затем исчезать в подключенных ссылках, но до сих пор я не смог элегантно исчезать в подключенных узлах, которые являются дочерними элементами текущего наведения мыши узел.

Это ключевая функция из кода:

function fade(opacity) {
    return function(d, i) {
        //fade all elements
        svg.selectAll("circle, line").style("opacity", opacity);

        var associated_links = svg.selectAll("line").filter(function(d) {
            return d.source.index == i || d.target.index == i;
        }).each(function(dLink, iLink) {
            //unfade links and nodes connected to the current node
            d3.select(this).style("opacity", 1);
            //THE FOLLOWING CAUSES: Uncaught TypeError: Cannot call method 'setProperty' of undefined
            d3.select(dLink.source).style("opacity", 1);
            d3.select(dLink.target).style("opacity", 1);
        });
    };
}

Я получаю Uncaught TypeError: Cannot call method 'setProperty' of undefined ошибка при попытке установить непрозрачность на элемент, который я загрузил из источника.цель. Я подозреваю, что это не правильный способ загрузить этот узел как объект d3, но я не могу найти другой способ загрузить его, не повторяя все узлы снова, чтобы найти те, которые соответствуют цели или источнику ссылки. Чтобы сохранить производительность разумной, я не хочу перебирать все узлы больше, чем необходимый.

Я взял пример выцветания ссылок из http://mbostock.github.com/d3/ex/chord.html:

однако, это не показывает, как изменить узел, подключенный ребенка.

любые хорошие предложения о том, как решить или улучшить это будет яростно upvoted :)

1 67

1 ответ:

ошибка заключается в том, что вы выбираете объекты данных (D.source и D.target), а не элементы DOM, связанные с этими объектами данных.

у вас есть подсветка строки, но я бы, вероятно, объединил ваш код в одну итерацию, например:

 link.style("opacity", function(o) {
   return o.source === d || o.target === d ? 1 : opacity;
 });

выделение соседних узлов сложнее, потому что вам нужно знать соседей для каждого узла. Эту информацию не так легко определить с текущими данными структуры, так как все у вас есть как массив узлов, так и массив ссылок. Забудьте о DOM на секунду и спросите себя, как бы вы определили, есть ли два узла a и b соседи?

function neighboring(a, b) {
  // ???
}

дорогой способ сделать это-перебрать все ссылки и посмотреть, есть ли ссылка, которая соединяет a и b:

function neighboring(a, b) {
  return links.some(function(d) {
    return (d.source === a && d.target === b)
        || (d.source === b && d.target === a);
  });
}

(это предполагает, что ссылки неориентированы. Если вы хотите выделить только подключенные вперед соседи, то исключите второй половина операционной.)

более эффективный способ вычисления этого, если вам приходится делать это часто,-это иметь карту или матрицу, которая позволяет постоянно проверять, являются ли A и b соседями. Например:

var linkedByIndex = {};
links.forEach(function(d) {
  linkedByIndex[d.source.index + "," + d.target.index] = 1;
});

теперь вы можете сказать:

function neighboring(a, b) {
  return linkedByIndex[a.index + "," + b.index];
}

и таким образом, теперь вы можете перебирать узлы и корректно обновлять их непрозрачность:

node.style("opacity", function(o) {
  return neighboring(d, o) ? 1 : opacity;
});

(вы также можете выбрать специальный случай, когда сама ссылка mouseovered, либо установив a само-ссылка для каждого узла в linkedByIndex, или путем тестирования на d непосредственно при вычислении стиля, или с помощью a !важно css :hover стиль.)

последнее, что я бы изменил в вашем коде,-это использовать непрозрачность заполнения и непрозрачность штриха, а не непрозрачность, потому что они обеспечивают гораздо лучшую производительность.