2015-07-24 2 views
0

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

Я так структурирован мой код:

  1. Я вытащил данные из CSV
  2. Я создал функцию «Update», которая создает/изменяет массив данных в зависимости от ввода данных пользователя
  3. Я создал " чтобы каждый раз, когда пользователь меняет свой ввод (то есть каждый раз, когда вызывается функция «update»),

Первая часть моего кода, похоже, работает нормально. Массив данных создается из csv и динамически обновляется правильно.

Но когда график перерисовывается, некоторые изображения появляются на неправильном узле (хотя изображение, отображаемое в подсказке, является правильным).

Ниже приведена моя функция «рисования», я думаю, что здесь проблема.

function draw(nodes) { 

     var force = d3.layout.force() 
     .nodes(nodes) 
     .size([width, height]) 
     .on("tick", tick) 
     .charge(-0.01) 
     .gravity(0) 
     .start(); 

    function tick(e) { 

     // Set initial positions 
    nodes.forEach(function(d) { 
     d.radius = radius; 
     }); 


     var node = svg.selectAll(".node") 
        .data(nodes); 

     var newNode = node.enter().append("g") 
       .attr("class", "node") 
       .on("click", function(d) { 
            div.transition().duration(300).style("opacity", 1); 
            div.html("<img src=img_med/" + d.name + ".png >") 
            .style("left", (d3.event.pageX) + "px") 
            .style("top", (d3.event.pageY-10) + "px"); 
           }) 
       .on("mouseout", function (d) { div.transition().delay(1500).duration(300).style("opacity", 0);}); 

      newNode.append("image") 
      .attr("xlink:href", function(d) { return "img_med/" + d.name + ".png"; }) 
      .attr("x", -8) 
      .attr("y", -8) 
      .attr("width", 30) 
      .attr("height", 30) 
      .style("cursor", "pointer") 
      .call(force.drag); 

     node.exit().remove(); 

     node.each(moveTowardDataPosition(e.alpha)); 
     node.each(collide(e.alpha)); 
     node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); 

    } 

    function moveTowardDataPosition(alpha) { 
     return function(d) { 
     d.x += (x(d[xVar]) - d.x) * 0.1 * alpha; 
     d.y += (y(d[yVar]) - d.y) * 0.1 * alpha; 
     }; 
    } 

    // Resolve collisions between nodes. 
    function collide(alpha) { 
     var quadtree = d3.geom.quadtree(nodes); 
     return function(d) { 
     var r = d.radius + radius + padding, 
      nx1 = d.x - r, 
      nx2 = d.x + r, 
      ny1 = d.y - r, 
      ny2 = d.y + r; 
     quadtree.visit(function(quad, x1, y1, x2, y2) { 
      if (quad.point && (quad.point !== d)) { 
      var x = d.x - quad.point.x, 
       y = d.y - quad.point.y, 
       l = Math.sqrt(x * x + y * y), 
       r = d.radius + quad.point.radius + padding; 
      if (l < r) { 
       l = (l - r)/l * alpha; 
       d.x -= x *= l; 
       d.y -= y *= l; 
       quad.point.x += x; 
       quad.point.y += y; 
      } 
      } 
      return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1; 
     }); 
     }; 
    } 
} 

Любые помощь/предложения/указатели, чтобы помочь мне понять, почему неправильные изображения отображаются на верхней части этих узлов были бы оценены!

Сообщите мне, если что-то неясно.

Большое спасибо!

+0

Возможно, вам нужна ключевая функция (второй аргумент '.data()'), который сообщает D3, как сопоставлять существующие узлы и данные. Значение по умолчанию - по индексу, что, вероятно, не то, что вы хотите. –

+0

@LarsKotthoff спасибо за ваш комментарий, я все еще изучаю ключевые функции, но если я напишу что-то вроде: var node = svg.selectAll (". Node") .data (nodes, function (d) {return d. имя;}); Это должно работать правильно? – Charles

+0

Из вашего кода, похоже, должно быть, да. –

ответ

0

Хорошо, мне просто не хватало ключевой функции, чтобы рассказать D3, как соответствовать существующим узлам и данным.

я заменил

var node = svg.selectAll(".node") 
       .data(nodes); 

по

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

, и она работала. Спасибо Ларсу!

 Смежные вопросы

  • Нет связанных вопросов^_^