簡體   English   中英

根據d3.js中的另一個值修復節點位置

[英]Fix node position based on another value in d3.js

我有一個部隊指揮的布局。 節點是從json值派生的,這些json名稱的名稱為group,是節點,源,目標和值是鏈接。 json可以將值“ size”作為節點的一部分,我想看看是否可以使用該值來確定節點的放置位置0,即尺寸越大,在畫布上越高放置。

我有兩個問題。 a)我不知道d3.js是否會在json之上攜帶額外的元素,以及b)我不確定如何根據此'size'元素更改y屬性。

我嘗試過的代碼是:

     var width = 1400,
    height = 500

var color = d3.scale.category20();

var force = d3.layout.force()
    .charge(-100)
    .linkDistance(130)
    .size([width, height]);

var svg = d3.select("#chart").append("svg")
    .attr("width", width)
    .attr("height", height)
    .append("g")
    .call(d3.behavior.zoom().scaleExtent([1, 8]).on("zoom", zoom))
    .append("g");


function zoom() {
  svg.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
}

var endpoint = window.location.href+".json"


d3.json(endpoint, function(graph) {
  force
      .nodes(graph.nodes)
      .links(graph.links)
      .start();

  var link = svg.selectAll(".link")
      .data(graph.links)
      .enter().append("line")
      .attr("class", "link")
      .style("marker-end",  "url(#suit)");

  var node = svg.selectAll(".node")
      .data(graph.nodes)
      .enter().append("circle")
      .attr("class", "node")
      .attr("r", function(d) { return d.group * 3; })
      .attr("cy", function(d) { return d.group; })
      .style("fill", function(d) { return color(d.group); })
      .call(force.drag)
      .on('mouseover', connectedNodes)
      .on('mouseout', UnconnectedNodes)
      .on("click",  function(d) { getprofile2(d); });

      function getprofile2(d){      
        $.ajax({
          url: "/graph/show", 
          type: "GET", 
          dataType: 'html',
          data: {name: d.name},
          success: function(result) {
            $('.bchart-content').html(result);
            addGraph(result);
          }
        });
      }


  node.append("title")
      .text(function(d) { return d.name; });

  node.append("circle")
  .attr("r", function(d) { return d.group * 3; });

  force.on("tick", function() {
    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; });
  });


  //Toggle stores whether the highlighting is on
var toggle = 0;
//Create an array logging what is connected to what
var linkedByIndex = {};
for (i = 0; i < graph.nodes.length; i++) {
    linkedByIndex[i + "," + i] = 1;
};
graph.links.forEach(function (d) {
    linkedByIndex[d.source.index + "," + d.target.index] = 1;
});

//This function looks up whether a pair are neighbours
function neighboring(a, b) {
    return linkedByIndex[a.index + "," + b.index];
}



function connectedNodes() {
    if (toggle == 0) {
        //Reduce the opacity of all but the neighbouring nodes
        d = d3.select(this).node().__data__;
        node.style("opacity", function (o) {
            return neighboring(d, o) | neighboring(o, d) ? 1 : 0.1;
        });
        link.style("opacity", function (o) {
            return d.index==o.source.index | d.index==o.target.index ? 1 : 0.1;
        });
        //Reduce the op
        toggle = 1;
    } else {
        //Put them back to opacity=1
        node.style("opacity", 1);
        link.style("opacity", 1);
        toggle = 0;
    }
}


function UnconnectedNodes() {
node.style("opacity", 1);
        link.style("opacity", 1);
        toggle = 0;
}





graphRec=JSON.parse(JSON.stringify(graph));
function threshold(thresh) {
    graph.links.splice(0, graph.links.length);
        for (var i = 0; i < graphRec.links.length; i++) {
            if (graphRec.links[i].value > thresh) {graph.links.push(graphRec.links[i]);}
        }
    restart();
}
//Restart the visualisation after any node and link changes
function restart() {
    link = link.data(graph.links);
    link.exit().remove();
    link.enter().insert("line", ".node").attr("class", "link");
    node = node.data(graph.nodes);
    node.enter().insert("circle", ".cursor").attr("class", "node").attr("r", 5).call(force.drag);
    force.start();
}
});

但是什么都沒有改變。

我的數據如下所示:

{  
   "nodes":[  
      {  
         "name":"Et",
         "group":5
         "size":14
      },
      {  
         "name":"Non Qui",
         "group":5,
         "size":19
      },
      {  
         "name":"Officiis",
         "group":1
         "size":13
      },
      {  
         "name":"Bilbo",
         "group":1
         "size":10
      }
   ],
 "links":[  
      {  
         "source":1,
         "target":2,
         "value":2
      },
      {  
         "source":1,
         "target":3,
         "value":1
      }
 ]
}

是一個如何調整重力函數以產生您想要的效果的示例。 我還加了些搖晃以幫助擴散...

 var width = 960, height = 500, padding = 0, // separation between nodes maxRadius = 12; var n = 1000, // total number of nodes m = 10; // number of distinct layers var color = d3.scale.category10() .domain(d3.range(m)); var y = d3.scale.ordinal() .domain(d3.range(m)) .rangePoints([height, 0], 1); var nodes = d3.range(n).map(function() { var i = Math.floor(Math.random() * m), v = (i + 10) / m * -Math.log(Math.random()); return { radius: Math.sqrt(v) * maxRadius, color: color(i), cy: y(i) }; }); var force = d3.layout.force() .nodes(nodes) .size([width, height]) .gravity(0) .charge(0) .on("tick", tick) .start(); var svg = d3.select("body").append("svg") .attr("width", width) .attr("height", height); var circle = svg.selectAll("circle") .data(nodes) .enter().append("circle") .attr("r", function(d) { return d.radius; }) .style("fill", function(d) { return d.color; }) .call(force.drag); function tick(e) { var a = e.alpha; circle .each(gravity(.2 * a)) .each(collide(.5)) .attr("cx", function(d) { return brownian(dx, a); }) .attr("cy", function(d) { return brownian(dy, a); }); force.alpha(a / 0.99 * 0.999) } var brownian = (function(w) { return function(x, a) { return x + (Math.random() - 0.5) * w * a } })(10); // Move nodes toward cluster focus. function gravity(alpha) { return function(d) { dy += (d.cy - dy) * alpha; // dx += (d.cx - dx) * alpha; }; } // Resolve collisions between nodes. function collide(alpha) { var quadtree = d3.geom.quadtree(nodes); return function(d) { var r = d.radius + maxRadius + padding, nx1 = dx - r, nx2 = dx + r, ny1 = dy - r, ny2 = dy + r; quadtree.visit(function(quad, x1, y1, x2, y2) { if (quad.point && (quad.point !== d)) { var x = dx - quad.point.x, y = dy - quad.point.y, l = Math.sqrt(x * x + y * y), r = d.radius + quad.point.radius + (d.color !== quad.point.color) * padding; if (l < r) { l = (l - r) / l * alpha; dx -= x *= l; dy -= y *= l; quad.point.x += x; quad.point.y += y; } } return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1; }); }; } 
 circle { stroke: #fff; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> 

根據您的數據,代碼應類似於:

 var node = svg.selectAll(".node")
    .data(graph.nodes)
    .enter().append("circle")
    .attr("class", "node")
    .attr("r", function(d) { return d.group * 3; })
    .attr("cy", function(d) { return d.size; })
    .style("fill", function(d) { return color(d.group); })

實際的“ cy”也可能取決於繪圖區域的最大高度,因此您可能需要相應地縮放比例。

希望這可以幫助 :)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM