d3js多个网络问题

时间:2017-04-20 00:17:02

标签: d3.js d3-force-directed

情景:

我有d3呈现多个网络。

它由单个节点,多个连接的节点网络组成。

我正在尝试附加d3-force(模拟),以便在拖动时节点不重叠,整个网络保持相对定位。

使用了很多人的力量。

问题:

  1. 当模拟加载(simulation.restart())时,整个网络不断分散。所有节点/网络都无限期地移动。
  2. 即使拖动来自一个网络的节点,所有其他网络也会移动。
  3. 如果有人能指出我正确的解决方案,我将不胜感激。

    这是一个小小提琴:https://jsfiddle.net/pdubey84/or0tn49k/2/

    Network

    var nodes = [
      { id: "mammal", group: 0, label: "Mammals", level: 1 },
      { id: "dog"   , group: 0, label: "Dogs"   , level: 2 },
      { id: "cat"   , group: 0, label: "Cats"   , level: 2 },
      { id: "fox"   , group: 0, label: "Foxes"  , level: 2 },
      { id: "elk"   , group: 0, label: "Elk"    , level: 2 },
      { id: "insect", group: 1, label: "Insects", level: 1 },
      { id: "ant"   , group: 1, label: "Ants"   , level: 2 },
      { id: "bee"   , group: 1, label: "Bees"   , level: 2 },
      { id: "fish"  , group: 2, label: "Fish"   , level: 1 },
      { id: "carp"  , group: 2, label: "Carp"   , level: 2 },
      { id: "pike"  , group: 2, label: "Pikes"  , level: 2 },
      { id: "pike"  , group: 3, label: "Pikes"  , level: 1 },
      { id: "pike"  , group: 4, label: "Pikes"  , level: 1 },
      { id: "pike"  , group: 4, label: "Pikes"  , level: 1 },
      { id: "foo"  , group: 4, label: "foo"  , level: 1 },
        { id: "bar"  , group: 4, label: "bar"  , level: 1 }
    ]
    
    var links = [
        { target: "mammal", source: "dog" , strength: 0.7 },
        { target: "mammal", source: "cat" , strength: 0.7 },
      { target: "mammal", source: "fox" , strength: 0.7 },
      { target: "mammal", source: "elk" , strength: 0.7 },
      { target: "insect", source: "ant" , strength: 0.7 },
      { target: "insect", source: "bee" , strength: 0.7 },
      { target: "fish"  , source: "carp", strength: 0.7 },
      { target: "fish"  , source: "pike", strength: 0.7 },
      { target: "cat"   , source: "elk" , strength: 0.1 },
      { target: "carp"  , source: "ant" , strength: 0.1 },
      { target: "elk"   , source: "bee" , strength: 0.1 },
      { target: "dog"   , source: "cat" , strength: 0.1 },
      { target: "fox"   , source: "ant" , strength: 0.1 },
        { target: "pike"  , source: "cat" , strength: 0.1 },
        { target: "foo"  , source: "bar" , strength: 0.1 }
    ]
    
    
    
    function getNodeColor(node, neighbors) {
      return 'red'
    }
    
    
    function getLinkColor(node, link) {
      return '000'
    }
    
    var width = window.innerWidth
    var height = window.innerHeight
    
    var svg = d3.select('svg')
    svg.attr('width', width).attr('height', height)
    
    // simulation setup with all forces
    var linkForce = d3
      .forceLink()
      .id(function (link) { return link.id })
      .strength(function (link) { return link.strength })
    
    var simulation = d3
      .forceSimulation()
      .force('link', linkForce)
      .force('charge', d3.forceManyBody().strength(-500).distanceMax(50))
      .force('center', d3.forceCenter(width / 2, height / 2))
    
    
    var dragDrop = d3.drag().on('start', function (node) {
      node.fx = node.x
      node.fy = node.y
    }).on('drag', function (node) {
      simulation.alphaTarget(0.7).restart()
      node.fx = d3.event.x
      node.fy = d3.event.y
    }).on('end', function (node) {
      if (!d3.event.active) {
        simulation.alphaTarget(0)
      }
      node.fx = null
      node.fy = null
    })
    
    var linkElements = svg.append("g")
      .attr("class", "links")
      .selectAll("line")
      .data(links)
      .enter().append("line")
        .attr("stroke-width", 1)
          .attr("stroke", "rgba(50, 50, 50, 0.2)")
    
    var nodeElements = svg.append("g")
      .attr("class", "nodes")
      .selectAll("circle")
      .data(nodes)
      .enter().append("circle")
        .attr("r", 10)
        .attr("fill", getNodeColor)
        .call(dragDrop)
    
    
    simulation.nodes(nodes).on('tick', () => {
      nodeElements
        .attr('cx', function (node) { return node.x })
        .attr('cy', function (node) { return node.y })
      linkElements
        .attr('x1', function (link) { return link.source.x })
        .attr('y1', function (link) { return link.source.y })
        .attr('x2', function (link) { return link.target.x })
        .attr('y2', function (link) { return link.target.y })
    })
    
    simulation.force("link").links(links)
    

1 个答案:

答案 0 :(得分:0)

这两种行为都是预期的。这就是你可以为这些问题做的事情:

  1. 网络分散:我想你正在谈论拖动功能,因为加载时模拟只运行300个滴答。如果是这种情况,请使用simulation.alpha代替simulation.alphaTargetsimulation.alpha是控制熵的正确方法:

    simulation.alpha(0.7).restart();
    
  2. 当您拖动一个网络时,所有网络都会移动:这是因为您使用的是d3.forceCenter()。根据{{​​3}}:

      

    定心力均匀地转换节点,使得所有节点的平均位置(如果所有节点具有相同的权重,则为质心)位于给定位置。 (强调我的)

  3. 你可以做的是在第一次拖动时取消此力:

    simulation.force("center", null)
    

    以下是这两个变化的小提琴:API