2017-06-15 1 views
0

Ich habe eine Grafik gemacht und jetzt möchte ich gerichtete Links hinzufügen.Control Pfeilspitzen Dimension auf einem kraftgesteuerten Layout in d3.js

Ich habe ein Problem, weil ich die Funktion will, dass, wenn ich die Maus über den Link bewege, es größer wird und wenn ich auf den Knoten klicke, wird es größer und diese zwei Funktionen machen ein Durcheinander mit meinem Pfeil auf den Verbindungen.

Ich habe versucht, viele Lösungen hier auf Stackoverflow gefunden, aber nichts hat für mich funktioniert ... Kann mir jemand helfen? Dank

hier mein Code:

<!DOCTYPE html> 
     <meta charset="utf-8"> 
     <title>Modifying a force layout v4</title> 

     <style> 

     .link { 
      stroke: #3B3B3B; 
      /*stroke-width: 1px;*/ 
     } 

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

     .svg { 
      border:3px solid black; 
      border-radius:12px; 
      margin:auto; 
     } 
     #arrow { 
      fill:green; 
     } 

     </style> 
     <body> 
     Node: 
     <div id="log"></div> 
     Link: 
     <div id="log2"></div> 
     <script src="//d3js.org/d3.v4.js"></script> 
     <script> 



      var width = 960, 
      height = 500; 
      radius = 17; 

      var expnsed = false; 

      var color = d3.scaleOrdinal(d3.schemeCategory20); 

      var nodes = [], 
      links = []; 


      var charge = d3.forceManyBody().strength(-150); 
      var simulation = d3.forceSimulation() 
      .force("link", d3.forceLink().distance(130).strength(.7)) 
      .force("charge", charge) 
      // use forceX and forceY instead to change the relative positioning 
      // .force("centering", d3.forceCenter(width/2, height/2)) 
      .force("x", d3.forceX(width/2)) 
      .force("y", d3.forceY(height/2)) 
      .on("tick", tick); 


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

      svg.append("defs").append("marker") 
       .attr("id", "arrow") 
       .attr("viewBox", "0 -5 10 10") 
       .attr("refX", 15) 
       .attr("refY", 0) 
       .attr("markerWidth", 6) 
       .attr("markerHeight", 6) 
       .attr("orient", "auto") 
       //.attr("fill","red") 
      .append("svg:path") 
       .attr("d", "M0,-5L10,0L0,5"); 
      var url = "https://api.myjson.com/bins/lj6ob"; 
      d3.json(url, function(error, graph) { 
      if (error) throw error; 
      nodes = graph.nodes; 
      links=graph.links; 
      console.log("graph.links.length: "+links.length) 

      for (var i = 0; i < links.length; i++){ 
       links[i].source = find(links[i].source); 
       links[i].target = find(links[i].target); 
      } 

      console.log("Link source: " + links[0].target) 


      start(); 
      }) 

     function find(name){ 
      for(var i = 0; i < nodes.length; i++){ 
      if (name == nodes[i].id){ 
       console.log("name: " + name) 
       console.log("id: " + nodes[i].id) 
       return i; 
      } 
      } 
     } 


     function start() { 
      var nodeElements = svg.selectAll(".node").data(nodes, function(d){return d.id}); 
      var linkElements = svg.selectAll(".line").data(links).attr("class","links"); 
      //console.log(nodes) 
      nodeElements.enter().append("circle").attr("class", function(d) {return "node " + d.index; }).attr("r", 17).attr("fill", function(d) { return color(d.group); }); 
      linkElements.enter().insert("line", ".node").attr("class", "link").attr("stroke-width", function(d) { return Math.sqrt(d.value)*2;}); 

      d3.selectAll("line").attr("marker-end", "url(#arrow)"); 

      nodeElements.exit().remove(); 
      linkElements.exit().remove(); 

      simulation.nodes(nodes) 
      simulation.force("link").links(links) 
    // NOTE: Very important to call both alphaTarget AND restart in conjunction 
     // Restart by itself will reset alpha (cooling of simulation) 
     // but won't reset the velocities of the nodes (inertia) 

     //remove alpha for slow incoming!! 
     //.alpha(1) 
      simulation.alpha(1).restart(); 
     } 

     function tick() { 
      var nodeElements = svg.selectAll(".node"); 
      var linkElements = svg.selectAll(".link"); 

      linkElements.append("title") 
      .text(function(d) { return "value link: " + d.value; }); 

      linkElements.on("mouseover", function(d) { 
        var g = d3.select(this); // The node 
        document.getElementById('log2').innerHTML = '<br> '+d.value; 
        g.attr("stroke-width", function(d) { return Math.sqrt(d.value)*4; }) 
       }); 

      linkElements.on("mouseout", function(d) { 
      var g = d3.select(this); // The node 
      g.attr("stroke-width", function(d) { return Math.sqrt(d.value)*2; }) 
      }); 


      nodeElements.append("title") 
      .text(function(d) { 
       return "node name: "+d.id + ", node group: "+d.group; 
      }); 

      nodeElements.on("mouseout", function(d) { 
        var g = d3.select(this); // The node 
        g.attr("fill", function(d) { return color(d.group); }) 
       }) 
       .on("mouseover", function(d) { 
        document.getElementById('log').innerHTML = '<br> '+d.id; 
        var g = d3.select(this); // The node 
        g.attr("fill", "red") 
       }); 
      nodeElements.on("click",click); 

      nodeElements.call(d3.drag() 
       .on("start", dragstarted) 
       .on("drag", dragged) 
       .on("end", dragended)); 

      /*nodeElements.attr("cx", function(d,i) {return d.x; }) 
      .attr("cy", function(d) { return d.y; })*/ 
      nodeElements.attr("cx", function(d) { return d.x = Math.max(radius, Math.min(width - radius, d.x)); }) 
      .attr("cy", function(d) { return d.y = Math.max(radius, Math.min(height - radius, d.y)); }); 

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

     function click(d) { 
      d3.select(this).attr("r", 
       function(d){if (d3.select(this).attr("r")==17) {radius = 23;return "23"}else{radius = 17; return "17"}} 
      ); 
      //expand(); 
      var E = "E"; 
      if(d.id == E && expand){ 
      expand=false; 
      //expand_2(); 
      } 
     }; 

     function expand(){ 
      console.log("expand") 
      b = createNode("A") 
      nodes.push(b); 
      start(); 
     } 

     function expand_2(){ 
      d3.json("nodes_2.json", function(error, graph) { 
      for(var i = 0; i < graph.nodes.length; i++){ 
       var n = graph.nodes[i]; 
       nodes.push(n); 
      } 
      for(var i = 0; i < graph.links.length; i++){ 
       graph.links[i].source = find(graph.links[i].source) 
       graph.links[i].target = find(graph.links[i].target) 
       var l = graph.links[i]; 
       links.push(l); 
      } 
      start(); 
      }) 
     } 

     function zoomed() { 
      g.attr("transform", d3.event.transform); 
     } 

     function dragstarted(d) { 
      if (!d3.event.active) simulation.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) simulation.alphaTarget(0); 
      d.fx = null; 
      d.fy = null; 
     } 
     function createNode(id) { 
      return {id: id, x: width/2, y:height/2} 
     } 

     </script> 

Antwort

2

können Sie geben dem Pfeil eine feste Größe, wenn Sie markerUnits="userSpaceOnUse" definieren. Um die aktuellen Größen neu:

 svg.append("defs").append("marker") 
      .attr("id", "arrow") 
      .attr("viewBox", "0 -5 10 10") 
      .attr("refX", 15) 
      .attr("refY", 0) 
      .attr("markerUnits", "userSpaceOnUse") 
      .attr("markerWidth", 30) 
      .attr("markerHeight", 30) 
      .attr("orient", "auto") 

Wenn Sie die Markierung auf schweben skalieren mögen, könnte die beste Lösung ein zweites Markierungselement arrow-hover zu haben, die größer ist und dass Sie vorübergehend über CSS austauschen:

line { 
    marker-end: url(#arrow); 
} 
line:hover { 
    marker-end: url(#arrow-hover); 
} 
+0

danke, Ihre Lösung ist in Ordnung, aber wie kann ich den richtigen Pfeil auswählen, wenn ich die Größe ändern auf die Zeile schweben? –

+0

I zum Ändern der Größe des Link auf schweben bedeuten verwende ich diese Funktion: \t linkElements.on ("Mouseover", Funktion (d) { \t \t var g = d3.select (this); \t g.attr ("stroke -Breite“, Funktion (d) {return Math.sqrt (d.value) * 4; \t \t}) \t g.attr ("markerWidth", 20) \t \t .attr ("markerHeight", 20) ; \t}); aber ich kann nicht den richtigen Marker der Linie auswählen ... Ich habe auch g.selectAll ("Marker") versucht, aber hat nicht funktioniert ... –

+0

Sie benötigen unterschiedliche Identitäten für die Marker, sonst entweder alle sie, oder keine, werden rezisiert. Siehe Bearbeiten. – ccprog

Verwandte Themen