2016-04-25 56 views
0

是否可以使用您自己的自定義符號創建一個力導向圖?我知道你可以製作幾個不同的符號(圓形,十字形,菱形,方形,三角形,三角形),但沒有一個符合我的目的。以下是我想要實現的一個例子。本質上,我想代表節點作爲表。D3中的自定義力 - 導向符號(表格作爲節點)

enter image description here

編輯:

作爲一個起點,我想用武力向圖的例子中,邁克·博斯托克貼過here。基本上,我想用桌子或可能的任何其他自定義形狀替換圓圈。

var width = 1000; 
var height = 500; 
var color = d3.scale.category20(); 

var force = d3.layout.force() 
    .charge(-120) 
    .linkDistance(30) 
    .size([width, height]); 

var svg = d3.select('body').append('svg') 
    .attr('width', width) 
    .attr('height', height); 

d3.json('miserables.json', function(error, graph) { 
    if (error) { 
     throw error; 
    } 
    force 
     .nodes(graph.nodes) 
     .links(graph.links) 
     .start(); 

    var link = svg.selectAll('.link') 
     .data(graph.links) 
     .enter().append('line') 
     .attr('class', 'link') 
     .style('stroke-width', function(d) { 
      return Math.sqrt(d.value); 
     }); 

    var node = svg.selectAll('.node') 
     .data(graph.nodes) 
     .enter().append('circle') 
     // <--- I should probably append my custom shape here instead of the circle 
     .attr('class', 'node') 
     .attr('r', 5) 
     .style('fill', function (d) { 
      return color(d.group); 
     }) 
     .call(force.drag); 

    node.append('title') 
     .text(function (d) { 
      return d.name; 
     }); 

    force.on('tick', function() { 
     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; 
     }); 

     node.attr('cx', function (d) { 
       return d.x; 
     }) 
      .attr('cy', function (d) { 
      return d.y; 
     }); 
    }); 
}); 

編輯2:

多次嘗試後用表來取代常規的節點,我還沒有作出了很大的進步。雖然我能夠創建表格並將它們添加到網頁,但它們不是圖表的一部分。我無法抓住並移動桌子。這是一個工作Fiddle和以下是代碼。

我必須接近這個錯誤的角度。製作一張桌子似乎是最符合我需求的東西。製作我自己的SVG元素似乎會比它需要的更復雜。

var cols = [ 
    'Col 1', 
    'Col 2' 
]; 

var vals = [ 
    ['val 1', 'val2'], 
    ['val 3', 'val 4'] 
]; 

var width = 800; 
var height = 500; 
var radius = 50; 
var color = d3.scale.category20(); 


//**************************************************// 
//*************** Tables as nodes ******************// 
//**************************************************// 

var arr = []; 
var table; 

for (var i = 0; i < 5; i += 1) { 
    table = d3.select('#canvas').append('table'); 
    var thead = table.append('thead'); 
    var tbody = table.append('tbody'); 
    thead.append('thead') 
     .append('tr') 
     .selectAll('th') 
     .data(cols).enter() 
     .append('th') 
     .text(function(col) { 
      return col; 
     }); 
    var rows = tbody.append('tbody').selectAll('tr') 
     .data(vals, function (d) { 
      return d; 
     }) 
     .enter() 
     .append('tr'); 
    var cells = rows.selectAll('td') 
     .data(function (d) { 
      return d; 
     }) 
     .enter().append('td') 
     .text(function (d) { 
      return d; 
     }); 
    arr.push(table); 
} 

var force = d3.layout.force() 
    .nodes(arr) 
    .links([]) 
    .size(width, height) 
    .linkDistance(80) 
    .charge(-200) 
    .start(); 

force.on('tick', function() { 
    table.style('top', function (d) { 
     console.log(d); 
     return d; 
    }); 
}); 


//**************************************************// 
//****************** Old graph *********************// 
//**************************************************// 

var dataset = { 
    nodes: [ 
     {name: "Adam"}, 
     {name: "Bob"}, 
     {name: "Carrie"}, 
     {name: "Donovan"}, 
     {name: "Edward"}, 
     {name: "Felicity"}, 
     {name: "George"}, 
     {name: "Hannah"}, 
     {name: "Iris"}, 
     {name: "Jerry"} 
    ], 
    edges: [ 
     {source: 0, target: 1}, 
     {source: 0, target: 2}, 
     {source: 0, target: 3}, 
     {source: 0, target: 4}, 
     {source: 1, target: 5}, 
     {source: 2, target: 5}, 
     {source: 2, target: 5}, 
     {source: 3, target: 4}, 
     {source: 5, target: 8}, 
     {source: 5, target: 9}, 
     {source: 6, target: 7}, 
     {source: 7, target: 8}, 
     {source: 8, target: 9}, 
     {source: 8, target: 9} 
    ] 
}; 


var force2 = d3.layout.force() 
    .charge(-3000) 
    .linkDistance(200) 
    .size([width, height]) 
    .nodes(dataset.nodes) 
    .links(dataset.edges) 
    .start() 


var svg = d3.select('body').append('svg') 
    .attr('width', width) 
    .attr('height', height); 

var edges = svg.selectAll('line') 
    .data(dataset.edges) 
    .enter() 
    .append('line') 
    .attr('id', function (d, i) { 
     return 'edge' + i; 
    }) 
    .style('stroke', '#ccc') 
    .style('pointer-events', 'none'); 

var nodes = svg.selectAll('.node') 
    .data(dataset.nodes) 
    .enter() 
    .append('circle') 
    .attr({ 
     class: 'node' 
    }) 
    .attr('r', radius) 
    .style('fill', function (d, i) { 
     return color(i); 
    }) 
    .call(force2.drag); 

force2.on('tick', function() { 
    edges.attr({ 
     'x1': function (d) { 
      return d.source.x; 
     }, 
     'y1': function (d) { 
      return d.source.y; 
     }, 
     'x2': function (d) { 
      return d.target.x; 
     }, 
     'y2': function (d) { 
      return d.target.y; 
     } 
    }); 
    nodes.attr({ 
     'cx': function (d) { 
      return d.x = Math.max(radius, Math.min(width - radius, d.x)); 
     }, 
     'cy': function (d) { 
      return d.y = Math.max(radius, Math.min(height - radius, d.y)); 
     } 
    }); 
}); 
+0

你想要一個表作爲你的節點嗎? – thatOneGuy

+0

我想它可能是一個表 – Fjotten

+0

而不是創建一個圓圈,追加你想要的。所以你可以從數據創建一個表格。最好在小提琴上添加你的當前代碼,我可以看看 – thatOneGuy

回答

0

SVG具有您可以用它來組織一下就可以任意複雜的節點group元素。

此外,你不要使用SVG。您可以使用D3來操縱HTML表格元素的絕對位置。在你的例子中,tick更新了圓形元素的cx和cy屬性。它可以輕鬆更新絕對定位表格元素的頂部和左側屬性。

+0

當你說'你可以使用D3來操縱說,HTML表格元素的絕對位置。這將意味着我不能使用HTML表與力指向圖相結合,對嗎?我是否正確地認爲該圖只能將SVG元素作爲節點來處理? – Fjotten

+0

..已解答回答澄清 – Andrew

+0

我討厭這樣密集,但是你認爲你可以展示一些小東西來顯示你如何添加一張表作爲節點? 我明顯是一個D3 noob(我D3的第二天)太多以弄清楚。我所能做的就是單獨添加表格。我會添加一些代碼來說明這一點。感謝您的持續幫助! :) – Fjotten