2015-04-01 4 views
1

Как добавить дополнительные узлы в макет пакета D3.js, если он уже создан и отображается в элементе SVG? Пересчет всего pack является вариантом, но я хотел бы сделать вставку гораздо более бесшовной.Вставка узлов в макет D3 (разбиение на страницы на масштабирование)

Я ищу функцию pack().addNode(), которая позволяет мне вставлять дополнительные дочерние узлы в существующий листовой узел. Когда пользователь приближается к этому листовому узлу, листовой узел должен превратиться в родительский узел и отображать вставленные узлы в качестве своих дочерних элементов.

Просьба посмотреть at my fiddle here. Узел под названием subnode_jane должен получить детей в subnode_subnodes в качестве своих новых детей.

var subnode_subnodes = [{ 
    "name": "JanesDaughter", 
    "size": 1030 
}, { 
    "name": "JanesSon", 
    "size": 12000 
}]; 

function zoom(d) { 
    var focus0 = focus; 
    focus = d; 

    if (d.name === "subnode_jane") { 
     alert("Oh I see subnode_jane has unpaginated children; insert them now!"); 
    } 

/* ... */ 
} 

Дополнительно: При этом, было бы неплохо, если бы общий вид оригинальных узлов останется совсем то же самое. Благодаря!

Похожие: update a layout.pack in d3.js

+1

http://bl.ocks.org/mbostock/1095795, http://stackoverflow.com/questions/11606214/adding-and -removing-nodes-in-d3js-force-graph, http://stackoverflow.com/questions/21070899/d3-js-how-to-remove-nodes-when-link-data-updates-in-a-force -layout –

ответ

1

Please find my workaround solution here. (Обходной путь, потому что я не смог закодировать функцию расширения макета D3)

Мое решение - создать второй «виртуальный» пакет и использовать его координаты круга для интеграции в исходный пакет. Работает на меня.

// hard-coded function 
var virtualNodesByParentNode = function (d3NodeParentElement, nodeChildrenElementArray) { 
    root.children[0].children[0].children = subnode_subnodes; 
    // we need to do this because otherwise, the parent node object will be changed 
    var d3NodeParentElementClone = clone(d3NodeParentElement); 
    var pack = d3.layout.pack() 
     .padding(2) 
     // -1 is important to avoid edge overlap 
     .size([d3NodeParentElementClone.r * 2 - 1, d3NodeParentElementClone.r * 2 - 1]) 
     .value(function (d) { 
    return d.size; 
     }); 
    d3NodeParentElementClone.children = nodeChildrenElementArray; 
    var nodes = pack.nodes(d3NodeParentElementClone) 
    // absolute x,y coordinates calculation 
    var curChildnode; 
    for (var i = 1; i < nodes.length; i++) { 
     curChildnode = nodes[i]; 
     curChildnode.x = curChildnode.x - nodes[0].x + d3NodeParentElement.x; 
     curChildnode.y = curChildnode.y - nodes[0].y + d3NodeParentElement.y; 
     curChildnode.depth = d3NodeParentElement.depth + 1; 
     curChildnode.parent = d3NodeParentElement; 
    } 
    nodes.splice(0, 1); 
    return nodes; 
}; 

Условный условие в zoom функции:

if (d.name === "subnode_jane" && done === 0) { 
    done = 1; 
    var virtualNodes = virtualNodesByParentNode(d, subnode_subnodes); 
    d.children = virtualNodes; 
    // http://stackoverflow.com/a/5081471/2381339 
    nodes.push.apply(nodes, virtualNodes); 
    circle = svg.selectAll("circle") 
     .data(nodes) 
     .enter().append("circle") 
     .attr("class", function (d) { 
     return d.parent ? d.children ? "node" : "node node--leaf" : "node node--root"; 
    }) 
     .style("fill", function (d) { 
     return "red"; 
    }) 
     .on("click", function (d) { 
     if (focus !== d) zoom(d), d3.event.stopPropagation(); 
    }); 
    text.remove(); 
    text = svg.selectAll("text") 
     .data(nodes) 
     .enter().append("text") 
     .attr("class", "label") 
     .style("fill-opacity", function (d) { 
     return d.parent === root ? 1 : 0; 
    }) 
     .style("display", function (d) { 
     return d.parent === root ? null : "none"; 
    }) 
     .text(function (d) { 
     return d.name; 
    }); 
    circle = svg.selectAll("circle"); 
    node = svg.selectAll("circle,text"); 
    // zoom to current focus again (do the transformation of the updated elements) 
    zoomTo(view); 
    return zoom(d); 
} 
Смежные вопросы