d3.forcesimulation()链接距离

Tyl*_*wan 5 javascript svg d3.js

我在堆栈上四处寻找变化的链接距离,看来要改变链接距离,您需要实现一个函数,然后传递该函数以动态分配链接距离,如下所示:

function linkDistance(d) {
    return d.distance;
}
Run Code Online (Sandbox Code Playgroud)

然后我以为我可以传递给svg,但是返回函数错误而不是现有的linkdistance或distance

var link = svg.selectAll(".link")
  .data(bilinks)    
  .enter().append("path")
  .style("stroke", "#6b7071")    //gunmetal grey link
  .attr("class", "link")
  .linkDistance(linkDistance)
  .attr("fill", "none")
Run Code Online (Sandbox Code Playgroud)

使用文档中的.linkDistance:https : //github.com/d3/d3/blob/master/API.md#forces-d3-force理想情况下,我想修改参数,例如链接距离,电荷,力和使用数据链接颜色就像我对点的颜色所做的一样,但是,我认为我缺乏有关如何正确执行此操作的知识。例如在代码的最后一行中,如果我要将from:to更改为

.style("stroke", "#6b7071")    //gunmetal grey link

.style("stroke", function(d) { return color(d.group);})
Run Code Online (Sandbox Code Playgroud)

链接颜色是一种颜色,而我希望根据组别选择39种颜色。此外,我也尝试过

 var simulation = d3.forceSimulation()
    .force("link", d3.forceLink().distance(function(d) {return d.distance}).strength(0.1))
    .force("charge", d3.forceManyBody(30))
    .force("center", d3.forceCenter(width / 2, height / 2));
Run Code Online (Sandbox Code Playgroud)

更新:我不确定长度的数据在链接和双链接的数组中,以便我可以引用距离,但是似乎无法使用数组中的值,但是console.log显示它已正确存储

<!DOCTYPE html>
<meta charset="utf-8">
<style>

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



</style>
<svg width="15000" height="15000"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>

//change background color to black
backgroundColor = d3.rgb('#000000')
d3.select("body").style("background-color", backgroundColor)

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

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

 var simulation = d3.forceSimulation()
    .force("link", d3.forceLink().distance(500).strength(0.1))
    .force("charge", d3.forceManyBody())
    .force("center", d3.forceCenter(width / 2, height / 2));


d3.json("hc7data.json", function(error, graph) {
  if (error) throw error;


  var nodes = graph.nodes,
      nodeById = d3.map(nodes, function(d) { return d.id; }),
      links = graph.links,
      bilinks = [];


//get graphics to make color scale us scaleOrdinal if every color chosen
  var color = d3.scaleOrdinal()  
      .domain([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40])
      .range(["#af1f45", "#be4f5e","#cd767c","#dc9d9e","#ecc9c8","#fbdbe9","#f7bbd5","#f49ac1","#f179ae","#ef509c",
      "#e3d4e4","#cdb1cf","#9a5699","#b990ba", "#a973a9","#d6eaf3","#b0daeb","#8acce4","#5ebfde","#00a5db","#6dbe46","#e0efd4",
      "#c3e0ae","#a7d48b","#8cc866","#fff2d1","#ffe8a8","#ffdf80","#ffd751","#fecf07","#fee1c9","#fcc79c","#faae74","#f69d58",
      "#f7964a","#fde3d9","#fcccbc","#f58870","#f9b4a0","#f79e87"]);


  links.forEach(function(link) {
    var s = link.source = nodeById.get(link.source),
        t = link.target = nodeById.get(link.target),
        i = {}, // intermediate node
        linkDist = link.distance;
    nodes.push(i);
    //console.log(linkDist);
    links.push({source: s, target: i, linkDist:linkDist}, {source: i, target: t, linkDist:linkDist });
    bilinks.push([s, i, t,linkDist]);
  });

  var link = svg.selectAll(".link")
    .data(bilinks)  
    .enter().append("path")
    .style("stroke", "#6b7071")    //gunmetal grey
    .attr("class", "link")
    .attr("fill", "none")



  var node = svg.selectAll(".node")
    .data(nodes.filter(function(d) { return d.id; }))
    .enter().append("circle")
      .attr("class", "node")
      //change circle size according to new function
      .attr("r", function(d) {return d.size})
      .attr("fill", function(d) { return color(d.group); })
      .style("stroke", "#000000")
      //.style("stroke", function(d) { return color(d.group); })
      .call(d3.drag()
          .on("start", dragstarted)
          .on("drag", dragged)
          .on("end", dragended));

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

  simulation
      .nodes(nodes)
      .on("tick", ticked);

  simulation.force("link")
      .links(links);

  function ticked() {
    link.attr("d", positionLink);
    node.attr("transform", positionNode);
  }
});




function positionLink(d) {
  return "M" + d[0].x + "," + d[0].y
       + "S" + d[1].x + "," + d[1].y
       + " " + d[2].x + "," + d[2].y;
}

function positionNode(d) {
  return "translate(" + d.x + "," + d.y + ")";
}

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;
}



</script>
Run Code Online (Sandbox Code Playgroud)

json doc样本

{
  "nodes": [
  {
    "id": "test1",
    "group": 1,
    "size": 10
  },
  {
    "id": "test2",
    "group": 1,
    "size": 10
  } 
  ],
  "links": [
  {
    "source": "test1",
    "target": "test2",
    "value": 1,
    "distance": 5
  },
  {
    "source": "test2",
    "target": "test1",
    "value": 1,
    "distance": 5
  } 
  ]
}
Run Code Online (Sandbox Code Playgroud)

小智 5

我相信你快到了。使用类似的自定义函数 function(d) {return d.distance}是正确的方法。但是,由于链接已经包含JSON文件的属性,因此您无需在links数组中推送额外的信息。

如前所述,可以声明模拟使用distance属性,如下所示:

var simulation = d3.forceSimulation()
    .force("link", d3.forceLink().distance(function(d) {return d.distance;}).strength(0.1))
Run Code Online (Sandbox Code Playgroud)

并且没有必要将其他信息推送到links数组,因此您可以删除以下行:

links.push({source: s, target: i, linkDist:linkDist}, {source: i, target: t, linkDist:linkDist });
Run Code Online (Sandbox Code Playgroud)

我创建了带有一些修改的JSON的JSFiddle,以在此处显示结果。我向距离较短的另一个节点添加了一个额外的链接,以显示效果。