2013-09-12 2 views
0

Я пытаюсь создать анимированную диаграмму с использованием d3js. Кажется, что это работает, за исключением одной маленькой вещи: когда я изменяю размер узлов, они начинают перекрываться.D3js collision не обновляется

Мой коллега и я были у него все утро, но мы, кажется, пропали без вести или чего-то не замечали.

Наш HTML/JS:

.node { 
    stroke: #fff; 
    stroke-width: 1.5px; 
} 

.link { 
    stroke: #999; 
    stroke-opacity: .6; 
} 

</style> 
<body> 

<div class="buttons"> 
    <button id="twelve">2012</button> 
</div> 

<script src="http://d3js.org/d3.v3.min.js"></script> 
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script> 

<script> 

var width = 960, 
    height = 500; 

var force = d3.layout.force() 
    .charge(0.5) 
    .gravity(0.2) 
    .distance(500) 
    .size([width, height]); 

var svg = d3.select("body").append("svg") 
    .attr("width", width) 
    .attr("height", height); 

d3.json("miserables.json", function(error, graph) { 
    force 
     .nodes(graph.nodes) 
     .distance(function(d){ return d.radius}) 
     .start(); 

var node = svg.selectAll(".node") 
    .data(graph.nodes) 
    .enter().append("circle") 
     .attr("class", "node") 
     .attr("r", function(d) { return d.radius; }) 
     .style("fill", function(d) { return d.color; }) 
     .call(force.drag); 

    node.append("title") 
     .text(function(d) { return d.name; }); 

    force.on("tick", function(e) { 
    node.attr("cx", function(d) { return d.x; }) 
     .attr("cy", function(d) { return d.y; }) 

     var nodes = graph.nodes 
     var q = d3.geom.quadtree(nodes), 
     i = 0, 
     n = nodes.length; 

    while (++i < n) { 
    q.visit(collide(nodes[i])); 
    } 

    svg.selectAll("circle") 
     .attr("cx", function(d) { return d.x; }) 
     .attr("cy", function(d) { return d.y; }) 
    }); 


    $(document).ready(function(){ 

     $('.buttons button').on('click', function(){ 
      var showYear = $(this).attr('id'); 
      node.transition() 
      .duration(350) 
      .attr("r", function(d){ return d[showYear]["radius"]}) 
      .style("fill", function(d){ return d[showYear]["color"]}) 
     }); 
    }) 



}); 


function collide(node) { 

    var r = node.radius + 16, 
     nx1 = node.x - r, 
     nx2 = node.x + r, 
     ny1 = node.y - r, 
     ny2 = node.y + r; 
    return function(quad, x1, y1, x2, y2) { 
    if (quad.point && (quad.point !== node)) { 
     var x = node.x - quad.point.x, 
      y = node.y - quad.point.y, 
      l = Math.sqrt(x * x + y * y), 
      r = node.radius + quad.point.radius; 
     if (l < r) { 
     l = (l - r)/l * .5; 
     node.x -= x *= l; 
     node.y -= y *= l; 
     quad.point.x += x; 
     quad.point.y += y; 
     } 
    } 
    return x1 > nx2 
     || x2 < nx1 
     || y1 > ny2 
     || y2 < ny1; 
    }; 

} 



</script> 

</body> 

и это наш файл в формате JSON:

{ 
     "nodes":[ 
     { 
      "name":  "Country One", 
      "radius": 40, 
      "color": "#ff0000", 
      "twelve" : { 
       "radius" : 60, 
       "color" : "#0ff000" 
       } 
      }, 
      { 
      "name":  "Country Two", 
      "radius": 40, 
      "color": "#ffff00", 
      "twelve" : { 
       "radius" : 60, 
       "color" : "#0ff000" 
       } 
      } 

     ] 
    } 

Любая помощь будет принята с благодарностью.

+0

Вы пробовали перезагрузить схему силы после обновления размеров? –

ответ

1

Обнаружение столкновений выполняется на основе атрибута radius узлов, но я предполагаю, что вы анимации только радиуса ваших кругов SVG, а не атрибута radius данных позади них.

Предлагаемое решение:

node 
    .each(function(d) { 
     d.radius = d[showYear]["radius"]; 
    }) 
    .transition() 
    .duration(350) 
    .attr("r", function(d){ return d.radius}) 
    .style("fill", function(d){ return d[showYear]["color"]}) 

Что же немного странно на мой взгляд, но может быть в порядке: Во время создания есть d.radius:

.attr("r", function(d) { return d.radius; }) 

, но позже он становится d[showYear]["radius"];. Имейте в виду, что объект d содержит только данные для один узел, но не все из них.

+0

Вы, сэр, заслуживаете медалью, или, по крайней мере, авантюру. Работала отлично (после вызова force.start()), спасибо! (D [showYear] ["radius"]; содержит новый радиус для обновленного круга) – Frank