【问题标题】:Why image doesn't attach to the nodes in this d3 code?为什么图像不附加到此 d3 代码中的节点?
【发布时间】:2018-09-17 23:47:54
【问题描述】:

我试图在强制布局中使用图像作为节点,但是我不知道如何指定图像的 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>

如何找到所有节点的坐标,如果节点是圆形的而图像是方形的,如何让图像被节点剪裁?

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

【问题讨论】:

    标签: image d3.js svg


    【解决方案1】:

    您正在附加 &lt;image&gt; 元素,而不是圆圈(您使用 selectAll("circle") 的事实没有区别)。因此,您应该在tick 函数中使用xy。除此之外,您应该将图像移动一半的宽度/高度:

    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;
        });
    
    });
    &lt;script src="https://d3js.org/d3.v4.min.js"&gt;&lt;/script&gt;

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

    【讨论】:

    • 在另一个示例中对于分组的圆圈/图像元素是否有任何理由,必须使用平移变换,而指定圆圈的 cx cy 不起作用? nodeCircle.attr("x", function(d) { return d.cx - 8; }) .attr("y", function(d) { return d.cy - 8; });并剪辑成圆形,是否需要指定一个剪辑路径?谢谢
    • @santoku 那是因为在示例中我使用组 (&lt;g&gt;) 元素来附加圆圈和图像。是的,您需要使用 clipPath,但在该示例中,图标已经是圆形的!就像你的 GitHub 图标一样。
    • 我现在明白了,只是想知道不使用组的缺点是什么,将所有内容附加到圆圈以了解 g 元素
    • 如果您不想使用组,则无需使用...但是,在勾选功能中,您必须同时移动圆圈和图像。另一种解决方案是使用模式。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-09-09
    • 1970-01-01
    • 2015-10-15
    • 2018-02-07
    • 1970-01-01
    • 2022-01-18
    • 1970-01-01
    相关资源
    最近更新 更多