Подтвердить что ты не робот

Добавление и удаление узлов в D3js Force Graph

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

force.nodes(json.nodes)
    .links(json.links)
    .start();

initNodes(json);

Как я могу сделать это более динамичным или обновить его без сброса всей визуализации?

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

4b9b3361

Ответ 1

Добавление узлов/ссылок в мой график силы D3 было очень запутанным, пока я не понял, как я добавлял начальный набор узлов.

Предполагая, что <g> вы хотите использовать для своих узлов:

// Select the element where you'd like to create the force layout
var el = d3.select("#svg");

// This should not select anything
el.selectAll("g")

// Because it being compared to the data in force.nodes() 
    .data(force.nodes())

// Calling `.enter()` below returns the difference in nodes between 
// the current selection and force.nodes(). At this point, there are
// no nodes in the selection, so `.enter()` should return 
// all of the nodes in force.nodes()
    .enter()

// Create the nodes
    .append("g")
    .attr("id", d.name)
    .classed("manipulateYourNewNode", true);

Теперь сделаем эту функцию, которая добавит node в макет после инициализации графика!

newNodeData - это объект с данными, которые вы хотите использовать для нового node. connectToMe - это строка, содержащая уникальный идентификатор node, который вы хотите связать с вашим новым node.

function createNode (newNodeData, connectToMe) {
    force.nodes().push(newNodeData);
    el.selectAll("g")
       .data(force.nodes(), function(datum, index) { return index })

Функция, заданная как необязательный второй аргумент в .data(), запускается один раз для каждого node в выборе и снова для каждого node в force.nodes(), сопоставляя их по возвращенному значению. Если функция не указана, вызывается функция возврата, которая возвращает index (как указано выше).

Однако, скорее всего, это будет спор между индексом вашего нового выбора (я считаю, что порядок случайным) и порядок в force.nodes(). Вместо этого вам, скорее всего, понадобится функция для возврата свойства, которое уникально для каждого node.

На этот раз .enter() вернет только node, который вы пытаетесь добавить как newData, потому что для него второй аргумент .data() не найден ключ.

       .enter()
       .insert("g", "#svg")
       .attr("id", d.name)
       .classed("manipulatYourNewNode", true);

    createLink(connectToMe, newNodeData.name);

    force.start();
}

Функция createLink (определенная ниже) создает связь между вашим новым node и вашим node по выбору.

Кроме того, API d3js заявляет, что force.start() следует вызывать после обновления макета.

Примечание: Вызов force.stop() в самом начале моей функции был огромной помощью для меня, когда я сначала пытался выяснить, как добавлять узлы и ссылки на мой график.

function createLink (from, to) {
    var source = d3.select( "g#" + from ).datum(),
        target = d3.select( "g#" + to ).datum(),
        newLink = {
            source: source,
            target: target,
            value: 1
        };
    force.links().push(newLink);

Код ниже работает в предположениях, что:

  • #links - это элемент оболочки, содержащий все ваши элементы ссылки.
  • Ваши ссылки представлены в виде <line> элементов:

    d3.select("#links")
        .selectAll("line")
        .data(force.links())
        .enter()
        .append("line");
    

Ответ 2

Здесь вы можете увидеть пример добавления новых узлов и связей: http://bl.ocks.org/2432083

Избавление от узлов и отношений немного сложнее, но вы можете увидеть процесс здесь: http://bl.ocks.org/1095795