在 d3.js 中添加节点特定链接到 forceSimulation 力导向图

时间:2020-12-23 06:39:16

标签: javascript html d3.js

我有这个力图。我想让每个圆圈都包含一个指向不同页面的链接,这样当点击查看者时就会重定向。

有没有办法做到这一点?

此外,也可以在每个节点(内部)附加文本会很好,但这不是优先事项。

var numNodes = 12
var nodes = d3.range(numNodes).map(function(d) {
  return {
    radius: Math.random() * 20 + 40
  }
})

var simulation = d3.forceSimulation(nodes)
  .force('charge', d3.forceManyBody().strength(4))
  .force('center', d3.forceCenter(400, 250))
  .force('collision', d3.forceCollide().radius(function(d) {
    return d.radius
  }))
  .on('tick', ticked);

function orb() {
  var u = d3.select('svg')
    .selectAll('circle')
    .data(nodes)

  u.enter()
    .append('circle')
    .attr('r', function(d) {
      return d.radius
    })
    .merge(u)
    .attr('cx', function(d) {
      return d.x
    })
    .attr('cy', function(d) {
      return d.y
    })

  u.exit().remove()
}

function ticked() {
  orb()
}
circle:hover {
  fill: red;
  stroke: #444;
  stroke-width: 0.5;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.5.0/d3.min.js"></script>

<svg width="800" height="800" class=''>
  <g>
  </g>
</svg>

1 个答案:

答案 0 :(得分:1)

看看这是否回答了您的两个问题。我评论的很好;如果有任何不清楚的地方,请告诉我:

<!DOCTYPE html>

<html>
  <head>
    <style>
      circle:hover {
        fill: red;
        stroke: #444;
        stroke-width: 0.5;
      }
      text {
        fill: #fff;
      }
    </style>
  </head>

  <body>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.5.0/d3.min.js"></script>

    <svg width="800" height="800" class="">
      <g></g>
    </svg>

    <script>
      var numNodes = 12;
      var nodes = d3.range(numNodes).map(function (d) {
        return {
          radius: Math.random() * 20 + 40,
          link:
            Math.random() < 0.5
              ? 'https://www.wikipedia.org'
              : 'https://www.google.com',
          text: Math.random() < 0.5 ? 'text' : 'string'
        };
      });

      var simulation = d3
        .forceSimulation(nodes)
        .force('charge', d3.forceManyBody().strength(4))
        .force('center', d3.forceCenter(400, 250))
        .force(
          'collision',
          d3.forceCollide().radius(function (d) {
            return d.radius;
          })
        )
        .on('tick', ticked);

      function orb() {

        // update selection
        let g = d3.select('svg')
          .selectAll('g')
          .data(nodes);

        // enter selection
        let ge = 
          g.enter()
          .append('g');
        
        // on enter append `a`
        // around the circle
        ge
          .append('a')
          .attr('href', function (d) {
            return d.link;
          })
          .attr('target', '_blank')
          .append('circle')
          .attr('r', function (d) {
            return d.radius;
          });

        // on enter create text element
        // for each circle
        ge
          .append('text')
          .attr('text-anchor', 'middle')
          .text(function(d){
            return d.text;
          })

        // merge update and enter
        g = ge.merge(g);

        // position circle
        g
          .selectAll('circle')
          .attr('cx', function (d) {
            return d.x;
          })
          .attr('cy', function (d) {
            return d.y;
          })

        // position text "in" circle
        g.selectAll('text')
          .attr('transform', function(d){
            return 'translate(' + d.x + ',' + d.y + ')';
          })

        g.exit().remove();
      }

      function ticked() {
        orb();
      }
    </script>
  </body>
</html>