web-dev-qa-db-fra.com

Fix Node Position dans la mise en page dirigée D3 Force

Je veux que certains des nœuds de ma disposition dirigée par la force ignorent toutes les forces et restent dans des positions fixes en fonction d'un attribut du nœud, tout en pouvant être traînés et exercer une répulsion sur d'autres nœuds et maintenir leurs lignes de liaison.

Je pensais que ce serait aussi simple que cela:

force.on("tick", function() {
    vis.selectAll("g.node")
        .attr("transform", function(d) {
            return (d.someAttribute == true) ?
               "translate(" + d.xcoordFromAttribute + "," + d.ycoordFromAttribute +")" :
               "translate(" + d.x + "," + d.y + ")"
        });
  });

J'ai également essayé de définir manuellement les attributs x et y du nœud à chaque tick, mais les liens continuent de flotter vers l'endroit où le nœud serait s'il était affecté par la force.

Évidemment, j'ai un malentendu fondamental sur la façon dont cela est censé fonctionner. Comment puis-je fixer des nœuds dans une position, tout en conservant les liens et en permettant qu'ils soient glissables?

64
Elijah

Ensemble d.fixed sur les nœuds souhaités sur true, et initialisez d.x et d.y à la position souhaitée. Ces nœuds feront alors toujours partie de la simulation, et vous pouvez utiliser le code d'affichage normal (par exemple, définir un attribut de transformation); cependant, comme ils sont marqués comme fixes, ils ne peuvent être déplacés qu'en les faisant glisser et non par la simulation.

Voir la documentation de mise en page forcée pour plus de détails ( documents v , documents actuels ), et aussi voir comment le nœud racine est positionné dans cet exemple .

75
mbostock

Noeuds fixes dans la disposition forcée pour d3v4 et d4v5

Dans d3v3 d.fixed fixera les nœuds à d.x et d.y; cependant, en d3v4/5, cette méthode n'est plus prise en charge. documentation d indique:

Pour fixer un nœud dans une position donnée, vous pouvez spécifier deux propriétés supplémentaires:

fx - the node’s fixed x-position

fy - the node’s fixed y-position

À la fin de chaque tick, après l'application de toute force, un nœud avec un nœud défini.fx a réinitialisé node.x à cette valeur et node.vx est mis à zéro; de même, un noeud avec un noeud.fy défini a noeud.y réinitialisé à cette valeur et noeud.vy mis à zéro. Pour supprimer un nœud qui a été précédemment résolu, définissez node.fx et node.fy sur null ou supprimez ces propriétés.

Vous pouvez définir les attributs fx et fy pour les nœuds de force dans votre source de données, ou vous pouvez ajouter et supprimer dynamiquement des valeurs fx et fy. L'extrait ci-dessous définit ces propriétés à la fin des événements de glisser, faites simplement glisser un nœud pour fixer sa position:

var data ={ 
 "nodes": 
  [{"id": "A"},{"id": "B"},{"id": "C"},{"id":"D"}], 
 "links": 
  [{"source": "A", "target": "B"}, 
   {"source": "B", "target": "C"},
   {"source": "C", "target": "A"},
   {"source": "D", "target": "A"}]
}
var height = 250;
var width = 400;

var svg = d3.select("body").append("svg")
  .attr("width",width)
  .attr("height",height);
  
var simulation = d3.forceSimulation()
    .force("link", d3.forceLink().id(function(d) { return d.id; }).distance(50))
    .force("charge", d3.forceManyBody())
    .force("center", d3.forceCenter(width / 2, height / 2));
    
var link = svg.append("g")
  .selectAll("line")
  .data(data.links)
  .enter().append("line")
  .attr("stroke","black");

var node = svg.append("g")
 .selectAll("circle")
 .data(data.nodes)
 .enter().append("circle")
 .attr("r", 5)
 .call(d3.drag()
   .on("drag", dragged)
   .on("end", dragended));
 
simulation
 .nodes(data.nodes)
 .on("tick", ticked)
 .alphaDecay(0);

simulation.force("link")
 .links(data.links);
      
function ticked() {
 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; });
 node
   .attr("cx", function(d) { return d.x; })
   .attr("cy", function(d) { return d.y; });
}    
    
function dragged(d) {
  d.fx = d3.event.x;
  d.fy = d3.event.y;
}

function dragended(d) {
  d.fx = d3.event.x;
  d.fy = d3.event.y;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.6.0/d3.min.js"></script>
25
Andrew Reid