Динамическое изменение симуляции макета Javascript D3 - PullRequest
1 голос
/ 15 сентября 2011

Я пытаюсь динамически изменить детали моделирования в примере D3 на https://github.com/mbostock/d3/blob/master/examples/force/force-multi-foci.html. Я поставил флажок и затем динамически назначил обработчик тика следующим образом (полный код на http://pastebin.com/k4P0uzHK):

$("#chkBox").change(function(){
  if ($(this).is(':checked')) {
    force.on("tick", forceTick);
  } else {
    force.on("tick", forceTick2);
  }
});

forceTick = function(e) {
  // Push different nodes in different directions for clustering.
  var ky = 400 * e.alpha;
  var kx = 20 * e.alpha;
  hLinks.forEach(function(hlink) {
    var yB = hlink.source.y, yT = hlink.target.y;
    if (yB<(yT+20)) { hlink.source.y += Math.min(ky,yT+20-yB); hlink.target.y -= Math.min(ky,yT+20-yB);}
    var xB = hlink.source.x, xT = hlink.target.x;
    if (xB<(xT-20)) { hlink.source.x += Math.min(kx,xT-20-xB); hlink.target.x -= Math.min(kx,xT-20-xB);}
    if (xB>(xT+20)) { hlink.source.x -= Math.min(kx,xB-xT-20); hlink.target.x += Math.min(kx,xB-xT-20);}

  });

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

  link.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; });
};


forceTick2 = function(e) {

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

  link.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; });
};

Но на самом деле кажется, что работает только тот обработчик, который указан первым. Есть ли способ динамического управления симуляцией?

Ответы [ 2 ]

4 голосов
/ 15 сентября 2011

Оператор on для принудительной разметки (и все, что использует d3.dispatch ) добавляет прослушиватель событий.Он не заменяет существующий прослушиватель событий.Схема принудительного размещения в настоящее время не предоставляет механизм удаления или замены существующего прослушивателя событий.

Это ошибка.Я намерен привести оператор макета on в соответствие с выборками, которые позволяют добавлять, заменять и удалять прослушиватели событий, вызывая on несколько раз.Вы по-прежнему сможете зарегистрировать несколько слушателей, если будете использовать пространства имен (такие как «tick.foo» и «tick.bar»).

Между тем, простое решение заключается в использовании одного метода какслушатель тиков, но затем используйте глобальное логическое значение, чтобы определить, какое из двух поведений вы хотите использовать для каждого тика.В вашем случае что-то вроде:

if (checked) {
  … clustering …
}
… update link positions …
… update node positions …

И плюс, что исключает дублирование кода.:)

1 голос
/ 24 августа 2017

Вы можете увидеть отличный пример этого здесь для d3.v4: https://bl.ocks.org/steveharoz/8c3e2524079a8c440df60c1ab72b5d03

Вы можете увидеть важные функции здесь:

// add forces to the simulation
function initializeForces() {
  // add forces and associate each with a name
  simulation
    .force("link", d3.forceLink())
    .force("charge", d3.forceManyBody())
    .force("collide", d3.forceCollide())
    .force("center", d3.forceCenter())
    .force("forceX", d3.forceX())
    .force("forceY", d3.forceY());
  // apply properties to each of the forces
  updateForces();
}

// apply new force properties
function updateForces() {
  // get each force by name and update the properties
  simulation.force("center")
    .x(width * forceProperties.center.x)
    .y(height * forceProperties.center.y);
  simulation.force("charge")
    .strength(forceProperties.charge.strength * forceProperties.charge.enabled)
    .distanceMin(forceProperties.charge.distanceMin)
    .distanceMax(forceProperties.charge.distanceMax);
  simulation.force("collide")
    .strength(forceProperties.collide.strength * forceProperties.collide.enabled)
    .radius(forceProperties.collide.radius)
    .iterations(forceProperties.collide.iterations);
  simulation.force("forceX")
    .strength(forceProperties.forceX.strength * forceProperties.forceX.enabled)
    .x(width * forceProperties.forceX.x);
  simulation.force("forceY")
    .strength(forceProperties.forceY.strength * forceProperties.forceY.enabled)
    .y(height * forceProperties.forceY.y);
  simulation.force("link")
    .id(function(d) {return d.id;})
    .distance(forceProperties.link.distance)
    .iterations(forceProperties.link.iterations)
    .links(forceProperties.link.enabled ? graph.links : []);

  // updates ignored until this is run
  // restarts the simulation (important if simulation has already slowed down)
  simulation.alpha(1).restart();
}
...