2016-06-24 3 views
3

Я пытался создать Складная макет силы с помощью d3js v4, похожий на этот: https://mbostock.github.io/d3/talk/20111116/force-collapsible.htmlВоссоздание разборный макет силы с помощью d3 v4

Я был в состоянии создать саму компоновку. Но не удалось его обновить. Может ли кто-нибудь помочь?

Вот мой JS код:

var width = 960, 
 
    height = 600; 
 

 
var root = { 
 
\t "name": "server1900", 
 
\t "children": [{ 
 
\t \t "name": "server913", 
 
\t \t "_children": null, 
 
\t \t "children": [{ 
 
\t \t \t "name": "server948" 
 
\t \t }, { 
 
\t \t \t "name": "server946" 
 
\t \t }] 
 
\t }, { 
 
\t \t "name": "server912", 
 
\t \t "_children": null, 
 
\t \t "children": [{ 
 
\t \t \t "name": "server984" 
 
\t \t }, { 
 
\t \t \t "name": "server983" 
 
\t \t }] 
 
\t }, { 
 
\t \t "name": "server911", 
 
\t \t "_children": null, 
 
\t \t "children": [{ 
 
\t \t \t "name": "server999", 
 
\t \t \t "_children": null, 
 
\t \t \t "children": [{ 
 
\t \t \t \t "name": "server992" 
 
\t \t \t }] 
 
\t \t }] 
 
\t }] 
 
}; 
 

 
root = d3.hierarchy(root); 
 

 
var i = 0; 
 

 
var transform = d3.zoomIdentity;; 
 

 
var nodeSvg, linkSvg, simulation, nodeEnter, linkEnter ; 
 

 
var svg = d3.select("body").append("svg") 
 
    .attr("width", width) 
 
    .attr("height", height) 
 
    .call(d3.zoom().scaleExtent([1/2, 8]).on("zoom", zoomed)) 
 
    .append("g") 
 
    .attr("transform", "translate(40,0)"); 
 

 
function zoomed() { 
 
    svg.attr("transform", d3.event.transform); 
 
} 
 

 
simulation = d3.forceSimulation() 
 
    .force("link", d3.forceLink().id(function(d) { return d.id; })) 
 
    .force("charge", d3.forceManyBody()) 
 
    .force("center", d3.forceCenter(width/2, height/2)) 
 
    .on("tick", ticked); 
 

 
update(); 
 

 
function update() { 
 
    var nodes = flatten(root); 
 
    var links = root.links(); 
 

 
    simulation 
 
    .nodes(nodes) 
 

 
    simulation.force("link") 
 
    .links(links); 
 

 
    linkSvg = svg.selectAll(".link") 
 
    .data(links, function(d) { return d.target.id; }) 
 

 
    linkSvg.exit().remove(); 
 

 
    linkSvg = linkSvg.enter() 
 
     .append("line") 
 
     .attr("class", "link"); 
 

 
    nodeSvg = svg.selectAll(".node") 
 
    .data(nodes, function(d) { return d.id; }) 
 

 
    nodeSvg.exit().remove(); 
 

 
    nodeSvg = nodeSvg.enter() 
 
    .append("g") 
 
     .attr("class", "node") 
 
     .on("click", click) 
 
     .call(d3.drag() 
 
     .on("start", dragstarted) 
 
     .on("drag", dragged) 
 
     .on("end", dragended)) 
 

 
    nodeSvg.append("circle") 
 
     .attr("r", 4 ) 
 
     .append("title") 
 
     .text(function(d) { return d.data.name; }) 
 

 
    nodeSvg.append("text") 
 
     .attr("dy", 3) 
 
     .attr("x", function(d) { return d.children ? -8 : 8; }) 
 
     .style("text-anchor", function(d) { return d.children ? "end" : "start"; }) 
 
     .text(function(d) { return d.data.name; }); 
 

 

 

 
} 
 

 
function ticked() { 
 
    linkSvg 
 
     .attr("x1", function(d) { return d.source.x; }) 
 
     .attr("y1", function(d) { return d.source.y; }) 
 
     .attr("x2", function(d) { return d.target.x; }) 
 
     .attr("y2", function(d) { return d.target.y; }); 
 

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

 
function click(d) { 
 
\t if (d.children) { 
 
\t \t d._children = d.children; 
 
\t \t d.children = null; 
 
    update(); 
 
    simulation.restart(); 
 
\t } else { 
 
\t \t d.children = d._children; 
 
\t \t d._children = null; 
 
    update(); 
 
    simulation.restart(); 
 
\t } 
 
} 
 

 
function dragstarted(d) { 
 
    if (!d3.event.active) simulation.alphaTarget(0.3).restart() 
 
    simulation.fix(d); 
 
} 
 

 
function dragged(d) { 
 
    simulation.fix(d, d3.event.x, d3.event.y); 
 
} 
 

 
function dragended(d) { 
 
    if (!d3.event.active) simulation.alphaTarget(0); 
 
    simulation.unfix(d); 
 
} 
 

 
function flatten (root) { 
 
    // hierarchical data to flat data for force layout 
 
    var nodes = []; 
 
    function recurse(node) { 
 
    if (node.children) node.children.forEach(recurse); 
 
    if (!node.id) node.id = ++i; 
 
    else ++i; 
 
    nodes.push(node); 
 
    } 
 
    recurse(root); 
 
    return nodes; 
 
}
line { 
 
    stroke: #666; 
 
} 
 

 
.node { 
 
    pointer-events: all; 
 
} 
 

 
circle { 
 
    stroke: none; 
 
    stroke-width: 40px; 
 
} 
 

 
.node text { 
 
    font: 8px sans-serif; 
 
}
<script src="https://d3js.org/d3.v4.0.0-alpha.50.min.js"></script>

Вот моя скрипка. https://jsfiddle.net/t4vzg650/4/

Благодаря

+0

Какие обновления вы имеете в виду? Есть ли какие-либо ошибки или это просто не показывает желаемого поведения? – altocumulus

+0

@altocumulus После нажатия на узел, если узел имеет дочерние элементы, дети будут разворачиваться/сворачиваться, т. Е. Карта обновляется, чтобы показать/скрыть новые узлы. Я имею в виду, что имеет обновление. Нет ошибок. Не показывать желаемое поведение. – kirupakaranh

+0

Вы уверены, что у d3.version.alpha нет ошибок? – Klaujesi

ответ

5

Я забыл слить старые узлы после ввода().

link = svg.selectAll(".link").data(links, function(d) { return d.target.id; }) 
var linkEnter = link.enter().append("line").attr("class", "link"); 
link = linkEnter.merge(link); 

Благодаря Майку Бостоку за помощь в решении этой проблемы. Я думал, что проблема с d3 v4, оказывается, я не читал изменений полностью: |

Смотрите это для получения дополнительной информации: https://github.com/d3/d3-force/issues/37

Fixed скрипку: https://jsfiddle.net/t4vzg650/6/

+1

Большая помощь. Для любого другого, кто это понимает, также может быть полезно использовать ключевую функцию (https://bost.ocks.org/mike/constancy/#key-functions), которую использует (@): @kirupakaranh: 'function (d) {return d.id; } '. Множество движущихся частей, а ключевая функция в дополнение к слиянию решила мою проблему. – ibgib