为什么图像不会附加到此d3代码中的节点?

时间:2018-04-08 13:29:57

标签: image d3.js svg

我试图在强制布局中使用图像作为节点,但我不知道如何指定图像的x,y位置:



<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <title>D3: Force layout</title>
  <script src="https://d3js.org/d3.v4.min.js"></script>
  <style type="text/css">
    /* No style rules here yet */
  </style>
</head>

<body>
  <script type="text/javascript">
    //Width and height
    var w = 500;
    var h = 300;

    //Original data
    var dataset = {
      nodes: [{
          name: "Adam"
        },
        {
          name: "Bob"
        },
        {
          name: "Carrie"
        },
        {
          name: "Donovan"
        },
        {
          name: "Edward"
        }
      ],
      edges: [{
          source: 0,
          target: 1
        },
        {
          source: 0,
          target: 2
        },
        {
          source: 0,
          target: 3
        },
        {
          source: 0,
          target: 4
        },
        {
          source: 1,
          target: 2
        },
        {
          source: 2,
          target: 3
        },
        {
          source: 1,
          target: 4
        }
      ]
    };

    //Initialize a simple force layout, using the nodes and edges in dataset
    var force = d3.forceSimulation(dataset.nodes)
      .force("charge", d3.forceManyBody())
      .force("link", d3.forceLink(dataset.edges))
      .force("center", d3.forceCenter().x(w / 2).y(h / 2));

    var colors = d3.scaleOrdinal(d3.schemeCategory10);

    //Create SVG element
    var svg = d3.select("body")
      .append("svg")
      .attr("width", w)
      .attr("height", h);


    //Create edges as lines
    var edges = svg.selectAll("line")
      .data(dataset.edges)
      .enter()
      .append("line")
      .style("stroke", "#ccc")
      .style("stroke-width", 1);

    //Create nodes as circles
    var nodes = svg.selectAll("circle")
      .data(dataset.nodes)
      .enter()
      .append("svg:image")
      .attr('x', function(d) {
        return d.x;
      })
      .attr('y', function(d) {
        return d.y;
      })
      .attr('width', 15)
      .attr('height', 15)
      .attr("xlink:href", "https://github.com/favicon.ico");



    //Every time the simulation "ticks", this will be called
    force.on("tick", function() {

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

      nodes.attr("cx", function(d) {
          return d.x;
        })
        .attr("cy", function(d) {
          return d.y;
        });

    });
  </script>
</body>

</html>
&#13;
&#13;
&#13;

如果节点是圆形的并且图像是方形的,我如何找到所有节点的坐标,并让节点剪切图像?

如果数据是json格式,每个节点都有自己的图像,我怎样才能将图像名称推送到原始数据?感谢。

1 个答案:

答案 0 :(得分:2)

您要追加<image>个元素,而不是圈子(您使用selectAll("circle")的事实没有区别)。因此,您应该在x函数中使用ytick。除此之外,你应该将图像移动宽度/高度的一半:

nodes.attr("x", function(d) { return d.x - 8; })
    .attr("y", function(d) { return d.y - 8; });

以下是更新后的代码:

var w = 500;
var h = 300;

//Original data
var dataset = {
  nodes: [{
      name: "Adam"
    },
    {
      name: "Bob"
    },
    {
      name: "Carrie"
    },
    {
      name: "Donovan"
    },
    {
      name: "Edward"
    }
  ],
  edges: [{
      source: 0,
      target: 1
    },
    {
      source: 0,
      target: 2
    },
    {
      source: 0,
      target: 3
    },
    {
      source: 0,
      target: 4
    },
    {
      source: 1,
      target: 2
    },
    {
      source: 2,
      target: 3
    },
    {
      source: 1,
      target: 4
    }
  ]
};

//Initialize a simple force layout, using the nodes and edges in dataset
var force = d3.forceSimulation(dataset.nodes)
  .force("charge", d3.forceManyBody())
  .force("link", d3.forceLink(dataset.edges))
  .force("center", d3.forceCenter().x(w / 2).y(h / 2));

var colors = d3.scaleOrdinal(d3.schemeCategory10);

//Create SVG element
var svg = d3.select("body")
  .append("svg")
  .attr("width", w)
  .attr("height", h);


//Create edges as lines
var edges = svg.selectAll("line")
  .data(dataset.edges)
  .enter()
  .append("line")
  .style("stroke", "#ccc")
  .style("stroke-width", 1);

//Create nodes as circles
var nodes = svg.selectAll("circle")
  .data(dataset.nodes)
  .enter()
  .append("svg:image")
  .attr('width', 16)
  .attr('height', 16)
  .attr("xlink:href", "https://github.com/favicon.ico");



//Every time the simulation "ticks", this will be called
force.on("tick", function() {

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

  nodes.attr("x", function(d) {
      return d.x - 8;
    })
    .attr("y", function(d) {
      return d.y - 8;
    });

});
<script src="https://d3js.org/d3.v4.min.js"></script>

另外,请注意您的节点现在不是圆形,并且没有剪裁图像。如果您想要附加图片圈子,就像看起来一样,您可以尝试不同的方法,例如:Making D3 like Force-Directed Graph with PNGs