D3节点选择如何在D3力图中工作?

时间:2016-08-11 21:54:17

标签: d3.js force-layout d3v4

我正在尝试创建一个强制图并为每个节点插入foreignObject。

    simulation
            .nodes(graph.nodes)
            .on("tick", ticked)
            .on("end", graphended);

       var node   = svg.append("g")
                    .attr("class", "nodes")
                    .selectAll("circle")
                    .data(graph.nodes)
                    .enter().append("foreignObject")
                                 .attr("width",img_w)
                                 .attr("height",img_h)
                            .append("xhtml:body")
                            .html(function(d){ 
                                return '<span class="custom-icon-container-circle">Some sample content</span>';
                            })
                            .call(d3.drag()
                                    .on("start", dragstarted)
                                    .on("drag", dragged)
                                    .on("end", dragended));

在TICK函数中,我按照以下方式分配xy坐标。

function ticked() {
            node
                .attr("x", function(d) {
                    var xPos = findPosX(d.x, img_w);
                    return xPos-img_w/2;
                })
                .attr("y", function(d) {
                    var yPos = findPosY(d.y, img_h);
                    return yPos-img_h/2;
                });
        }

但是在这个tick方法中,不是将xy位置赋予foreignObject,而是将位置分配给foreignObject中的body元素,该元素正在构成节点不是在实际坐标处的位置。

现在,代码确实有效(如果我删除foreignObject并放置另一个元素标记并且该位置被赋予该元素),所以我认为我的选择器和append语句中存在一个问题,上面创建了foreignObject ,因为它选择元素的内部。

1 个答案:

答案 0 :(得分:1)

d3方法链接返回返回内容的最后一件事,在您的情况下,这是.append("xhtml:body"),因此node持有对foreignObject的引用。将您的代码更改为:

var node = svg.append("g")
 .attr("class", "nodes")
 .selectAll("circle")
 .data(graph.nodes)
 .enter().append("foreignObject")
 .attr("width",img_w)
 .attr("height",img_h);

node.append("xhtml:body")
  .html(function(d){ 
    return '<span class="custom-icon-container-circle">Some sample content</span>';
  })
  .call(d3.drag()
  .on("start", dragstarted)
  .on("drag", dragged)
  .on("end", dragended));