2017-02-01 1 views
0

Я делаю диаграмму направленности с помощью D3 и получаю ее работу с кругами svg для узлов. Но когда я использую divs в комбинации с CSS left и top свойствами, узлы находятся вне позиции. Я не могу понять, что я делаю неправильно здесь. Я использую координаты x и y, которые заставляют D3 генерировать как левые и верхние свойства, но, возможно, это не путь?Как позиционировать узлы Принудительный график D3 с CSS?

Вот мои 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; 
} 

Graph до сих пор на codepen:

https://codepen.io/chemok78/full/VPMgGx/

+1

Проверить это http://stackoverflow.com/questions/36705237/precalculate-and-set-initial-positions-of-nodes-in-d3-js/36777595#36777595 –

ответ

2

счета за сколько ссылок в SVG смещены от окна: они сдвинуты на margin.left, вниз на margin.top, а также вниз по высотам <h1> и <h2> (плюс прокладка).

Например, в моем браузере, флаги выглядят правильно установлены с помощью следующего кода:

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

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

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

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

    }) 

Обратите внимание, что это происходит потому, что <div> флаг элементы имеют по умолчанию left и top атрибут 0, даже если их parent - <div#chart>. Я жестко закодировал 150, но вы также можете разработать способ динамического расчета.

Причина вы получили его работы с <circle> но не <div> в том, что круги SVG элементы и дети <svg>, так что они уже находятся в правильных исходных позициях. Там может быть альтернативное решение, в котором вы храните флаги в SVGs: добавление узлов как <g> или <rect> вместо <div>, атрибуты x и y вместо left и top, дети <svg> вместо <div#chart>. Однако я не изучил, как реализовать назначение флагов каждому узлу, потому что вы не указываете на отдельный URL-адрес для каждого файла флага.

0

Спасибо всем,

я в конечном итоге получить позицию SVG г элемента диаграммы с помощью Element.getBoundingClientRect() и используя левую верхнюю позицию, что в позиционировании всех узлов.

//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; 

     }) 

    }) 
Смежные вопросы