2017-07-25 6 views
0

J'essaye de créer une disposition de force avec d3.js v4 et la partie maire fonctionne très bien accepter pour un problème lors de l'utilisation du comportement de traînée .D3.js v4 force mise en page avec des forces de liaison provoque un mouvement étrange en utilisant le comportement de glisser

En cliquant sur un nœud pour le déplacer autour des autres noeuds, qui ne sont pas connectés au noeud cliqué, s'envoler:

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

function drawNode(nodes) { 
    return svg.selectAll("circle.node") 
     .data(nodes, function (d, i) { return d.Id; }) 
     .enter().append("circle") 
     .attr("class", "node") 
     .attr("r", 5) 
     .attr("fill", "blue") 
     .call(d3.drag() 
      .on("start", dragstarted) 
      .on("drag", dragged) 
      .on("end", dragended)); 
} 

function drawMainNode(nodes) { 
    return svg.selectAll("circle.mainnode") 
     .data(nodes, function (d, i) { return d.Id; }) 
     .enter().append("circle") 
     .attr("class", "mainnode") 
     .attr("r", 15) 
     .attr("fill", "red") 
     .call(d3.drag() 
      .on("start", dragstarted) 
      .on("drag", dragged) 
      .on("end", dragended)); 
} 

function drawLinks(links) { 
    return svg.selectAll("line") 
     .data(links, function (d, i) { return d.source + "-" + d.target; }) 
     .enter().append("line") 
     .attr("stroke-width", 3); 
} 

function dragstarted(d) { 
    if (!d3.event.active) dragSimualtion.alphaTarget(0.3).restart(); 
    d.fx = d.x; 
    d.fy = d.y; 
} 

function dragged(d) { 
    d.fx = d3.event.x; 
    d.fy = d3.event.y; 
} 

function dragended(d) { 
    if (!d3.event.active) dragSimualtion.alphaTarget(0); 
    d.fx = null; 
    d.fy = null; 
} 

function ticked() { 
    dLinks 
     .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; }); 

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

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

var dLinks = drawLinks(mainLinks.concat(nodeLinks)); 
var dNodes = drawNode(nodes); 
var dMainNodes = drawMainNode(mainNodes); 

var simulation = d3.forceSimulation(mainNodes.concat(nodes)) 
       .force("charge", d3.forceManyBody()) 
       .force("center", d3.forceCenter(width/2, height/2)) 
       .force("collide", d3.forceCollide(20).radius(20)) 
       .force("links", d3.forceLink(mainLinks.concat(nodeLinks)) 
        .id(function (d) { return d.Id; })) 
       .alpha(0.9) 
       .alphaDecay(0.1) 
       .on("tick", ticked); 

var dragSimualtion = d3.forceSimulation(mainNodes.concat(nodes)) 
       .force("collide", d3.forceCollide(20).radius(20)) 
       .force("links", d3.forceLink(mainLinks.concat(nodeLinks)) 
        .id(function (d) { return d.Id; })) 
       .alphaDecay(0.1) 
       .on("tick", ticked) 
       .stop() 

Plunkr

J'ai essayé d'utiliser une séparée simulation pour la traînée événement qui utilise uniquement la force de liaison et la force de collision - car les nœuds doivent être déplacés avec chaque nœud qui leur est rattaché et les autres nœuds non attachés doivent être repoussés, mais uniquement s'ils entrent en collision. Donc, la question est, comment puis-je empêcher les autres nœuds de voler autour?

Edit1: Ma première tentative a été en utilisant uniquement le premier objet de simulation, mais je pensais que l'effet observé est dû à la d3.forceManyBody en raison de sa force de répulsion. J'ai essayé de limiter cet effet avec distanceMax mais n'ai eu aucun succès. Ma deuxième tentative était d'utiliser un d3.forceSimulation séparé qui ne contient que les forces pertinentes pour l'animation glisser.

+0

Cela peut être dû à la combinaison de 'd3.forceManyBody' et' d3.forceCollide'. Et je ne pense pas vraiment que vous avez besoin de la simulation séparée pour l'événement de glisser. Juste mettre à jour celui par défaut. Voir https://bl.ocks.org/mbostock/2675ff61ea5e063ede2b5d63c08020c7 – mahish

+0

Ma première tentative a été d'utiliser une seule simulation, mais je pensais que l'effet de dérive des nœuds est causé par la force ManyBody (en raison de la répulsion), donc j'ai créé le deuxième simulation. J'ai également essayé d'utiliser disctanceMax() de d3.forceManyBody pour limiter la force de répulsion à une certaine portée. –

Répondre

0

la forceCollide de la fonction glisser semble être le problème ...

essayer:

.force("collide", d3.forceCollide(20).radius(20).strength(0)) 

vous obtiendrez alors le problème inverse, essayez entre 0 et 1, trouver celui que vous aimez.