Javascript 如何使用CSS定位节点强制有向图D3?

Javascript 如何使用CSS定位节点强制有向图D3?,javascript,css,d3.js,svg,data-visualization,Javascript,Css,D3.js,Svg,Data Visualization,我正在用D3制作一个力定向图,并使其与svg圆一起用于节点。但是当我将div与CSS的left和top属性结合使用时,节点的位置就不合适了。我不知道我在这里做错了什么。我使用力D3生成的x和y坐标作为左属性和顶属性,但这可能不是正确的方法 这是我的JS: var url = "https://raw.githubusercontent.com/DealPete/forceDirected/master/countries.json"; d3.json(url, function(json){

我正在用D3制作一个力定向图,并使其与svg圆一起用于节点。但是当我将div与CSS的left和top属性结合使用时,节点的位置就不合适了。我不知道我在这里做错了什么。我使用力D3生成的x和y坐标作为左属性和顶属性,但这可能不是正确的方法

这是我的JS:

var url = "https://raw.githubusercontent.com/DealPete/forceDirected/master/countries.json";

d3.json(url, function(json){

  var data = json;

  var margin = {top: 40, right: 40, bottom: 40, left: 40};

  var w = 1000 - margin.left - margin.right;
  var h = 1000 - margin.top - margin.bottom;

  var svg = d3.select("#chart")
              .append("svg")
                .attr("width", w + margin.left + margin.right)
                .attr("height", h + margin.top + margin.bottom)
              .append("g")
                .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

  var nodes = data.nodes;
  var links = data.links;

  //Create a force layout object and define its properties
  var force = d3.layout.force()
                .size([w,h])
                .nodes(nodes)
                .links(links);

  force.linkDistance(h/20);

  force.charge(-120)

  var link = svg.selectAll(".link")
                .data(links)
                .enter()
                .append("line")
                .attr("class", "link");

  var node = d3.select("#chart").selectAll(".node")
                .data(nodes)
                .enter()
                .append("div")

  force.on("end", function(){
  //set node and link position attributes once force calculations have finished  

    //position the nodes
    node.style("left", function(d){

            return d.x  + "px";

        })
        .style("top", function(d){

            return d.y + "px";

        })
        .attr("class", function(d){

            return "flag flag-" + d.code + " node";

        })
        .attr("src", "https://res.cloudinary.com/dettjqo9j/image/upload/v1485942660/flags_xf9dde.png");

    link.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;

        })



  })//force.on


  force.start();
  //let the force start its calculations

})
我的css:

svg {

  background-color: white;
  box-shadow: 0 0 10px #888888;

}

.link {

  stroke: #2c3e50;
  stroke-width: 2px;

}

.flag {
    display: inline-block;
    position:absolute;
    width: 16px;
    height: 11px;
    background: url('https://res.cloudinary.com/dettjqo9j/image/upload/v1485942660/flags_xf9dde.png') no-repeat;
}

.flag.flag-ml {
    background-position: -224px -88px;
}
到目前为止在codepen上的图表:


说明SVG中的链接与窗口的偏移量:它们被移动了
边距。向左移动了
,向下移动了
边距。向上移动了
,向下移动了
的高度(加上填充)

例如,在“我的浏览器”中,使用以下代码可以正确定位标志:

node.style("left", function(d){

        return d.x + margin.left + 150 + "px";

    })
    .style("top", function(d){

        return d.y + margin.top + "px";

    })
请注意,这是因为
标记元素具有默认的
left
top
属性0,即使它们的父元素是
。我已经硬编码了150,但是你也可以设计一种动态计算的方法


之所以使用
而不是
是因为圆是SVG元素和
的子元素,所以它们已经处于正确的起始位置。可能有另一种解决方案,您可以将标志保留在SVG中:将节点添加为
而不是
x
y
的属性而不是
的子节点而不是
。但是,我还没有探讨如何实现将标志分配给每个节点,因为您没有为每个标志文件指向一个不同的URL。

说明SVG中的链接与窗口的偏移量:它们被移动了
边距。左移了
,下移了
边距。上移了
,也可以向下移动
的高度(加上填充)

例如,在“我的浏览器”中,使用以下代码可以正确定位标志:

node.style("left", function(d){

        return d.x + margin.left + 150 + "px";

    })
    .style("top", function(d){

        return d.y + margin.top + "px";

    })
请注意,这是因为
标记元素具有默认的
left
top
属性0,即使它们的父元素是
。我已经硬编码了150,但是你也可以设计一种动态计算的方法

之所以使用
而不是
是因为圆是SVG元素和
的子元素,所以它们已经处于正确的起始位置。可能有另一种解决方案,您可以将标志保留在SVG中:将节点添加为
而不是
x
y
的属性而不是
的子节点而不是
。但是,我没有探讨如何实现将标志分配给每个节点,因为您没有为每个标志文件指向不同的URL。

谢谢大家

最后,我通过使用SVG g元素的左上方位置来定位所有节点,得到了图表中SVG g元素的位置

//Get position of g element of the chart
  var position = document.getElementById("area").getBoundingClientRect();

force.on("tick", function(){

    node.style("left", function(d){

            return d.x  + position.left + "px";

        })
        .style("top", function(d){

            return d.y  + position.top  +  "px";

        })
        .attr("class", function(d){

            return "flag flag-" + d.code + " node";

        })
        .attr("src", "https://res.cloudinary.com/dettjqo9j/image/upload/v1485942660/flags_xf9dde.png")

    link.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;

        })

  })
谢谢大家

最后,我通过使用SVG g元素的左上方位置来定位所有节点,得到了图表中SVG g元素的位置

//Get position of g element of the chart
  var position = document.getElementById("area").getBoundingClientRect();

force.on("tick", function(){

    node.style("left", function(d){

            return d.x  + position.left + "px";

        })
        .style("top", function(d){

            return d.y  + position.top  +  "px";

        })
        .attr("class", function(d){

            return "flag flag-" + d.code + " node";

        })
        .attr("src", "https://res.cloudinary.com/dettjqo9j/image/upload/v1485942660/flags_xf9dde.png")

    link.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;

        })

  })
看看这个看看这个