2016-07-04 71 views
4

我最近使用v3庫創建了我的第一個強制有向圖,但現在我需要使用D3版本4庫創建相同的圖形,但在v4中方法發生了巨大變化,現在我在3中的所有force()/ drag()方法現在不存在於v4中。難以將D3 v3 Force Directed圖轉換爲D3 v4庫實現?

My圖表是基於以下樣機 - http://www.ourd3js.com/wordpress/?p=606

是否有已在D3某處的V4庫中創建樣本庫,在這裏我可以看一看,瞭解一些功能,我可以代替這個特定圖表?

編輯:

我當前的代碼看起來是這樣,但我不能將它完全轉化,例如,節點鏈接是非常密切的,有時的鏈路和節點的文本是重疊的。

<svg width="960" height="600"></svg> 

JavaScript代碼

var svg = d3.select("svg"), 
    width = +svg.attr("width"), 
    height = +svg.attr("height"); 

var graph = root; 

var w = window, 
    d = document, 
    e = d.documentElement, 
    g = d.getElementsByTagName('body')[0], 
    x = w.innerWidth || e.clientWidth || g.clientWidth, 
    y = w.innerHeight|| e.clientHeight|| g.clientHeight; 

var width = x; 
var height = y; 
var img_w = 24; 
var img_h = 24; 
var k = Math.sqrt(root.nodes.length/(width * height)); 

var simulation = d3.forceSimulation() 
    .force("link", d3.forceLink().id(function(d) { return d.id; })) 
    .force("charge", d3.forceManyBody().strength(-5/k)) 
    .force("center", d3.forceCenter(width/2, height/2)); 

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

    var node = svg.append("g") 
        .attr("class", "nodes") 
        .selectAll("circle") 
        .data(graph.nodes) 
        .enter().append("image") 
          .attr("width",img_w) 
          .attr("height",img_h) 
          .attr("xlink:href",function(d){ 
           return d.image; 
          }) 
          .call(d3.drag() 
        .on("start", dragstarted) 
        .on("drag", dragged) 
        .on("end", dragended)); 

    var links_text = svg.selectAll(".linetext") 
         .data(graph.links) 
         .enter() 
         .append("text") 
         .attr("class","linetext slds-text-heading--small") 
         .attr("text-anchor", "middle") 
         .text(function(d){ 
          return '['+d.relation+']'; 
         }); 

    var nodes_text = svg.selectAll(".nodetext") 
         .data(graph.nodes) 
         .enter() 
         .append("text") 
         .attr("class","nodetext slds-text-heading--label") 
         .attr("text-anchor", "middle") 
         .attr("dx",-20) 
         .attr("dy",20) 
         .text(function(d){ 
          return (d.subname!=''?(d.subname+': '):'')+d.name; 
         }); 

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

    simulation.force("link") 
      .links(graph.links); 

    function ticked() { 
    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; }); 

    links_text 
     .attr("x",function(d){ return (d.source.x + d.target.x)/2; }) 
     .attr("y",function(d){ return (d.source.y + d.target.y)/2; }); 

    node 
     .attr("x", function(d) { return d.x; }) 
     .attr("y", function(d) { return d.y; }); 

    nodes_text 
     .attr("x",function(d){ return d.x + 20 }) 
     .attr("y",function(d){ return d.y + img_w/2; }); 
    } 


function dragstarted(d) { 
    if (!d3.event.active) simulation.alphaTarget(0.3).restart(); 
    d.fx = d.x; 
    d.fy = d.y; 
} 

function dragged(d) { 
    d.fx = d3.event.x; 
    d.fy = d3.event.y; 
} 

function dragended(d) { 
    if (!d3.event.active) simulation.alphaTarget(0); 
    d.fx = null; 
    d.fy = null; 
} 

JSON數據字符串

var root = { 
    "nodes" : [ { 
    "subname" : "", 
    "name" : "Telco Power Case", 
    "image" : "/node32.png", 
    "id" : 0 
    }, { 
    "subname" : "Contact", 
    "name" : "Suman Kumar", 
    "image" : "/subnode32.png.png", 
    "id" : 1 
    }, { 
    "subname" : "Contact", 
    "name" : "Karla Samuel", 
    "image" : "/subnode32.png.png", 
    "id" : 2 
    }, { 
    "subname" : "Account", 
    "name" : "Signa Tech", 
    "image" : "/subnode32.png.png", 
    "id" : 3 
    }, { 
    "subname" : "", 
    "name" : "Maven's Case", 
    "image" : "/node32.png", 
    "id" : 4 
    }, { 
    "subname" : "", 
    "name" : "Delta Case", 
    "image" : "/node32.png", 
    "id" : 5 
    }, { 
    "subname" : "Contact", 
    "name" : "T Browney", 
    "image" : "/subnode32.png.png", 
    "id" : 6 
    }, { 
    "subname" : "Account", 
    "name" : "Presto", 
    "image" : "/subnode32.png.png", 
    "id" : 7 
    }, { 
    "subname" : "Contact", 
    "name" : "Bob Tannenbaum", 
    "image" : "/subnode32.png.png", 
    "id" : 8 
    }, { 
    "subname" : "Account", 
    "name" : "Tesla Power", 
    "image" : "/subnode32.png.png", 
    "id" : 9 
    } ], 
    "links" : [ { 
    "target" : 1, 
    "source" : 0, 
    "relation" : "Trainee" 
    }, { 
    "target" : 2, 
    "source" : 0, 
    "relation" : "Manager" 
    }, { 
    "target" : 3, 
    "source" : 0, 
    "relation" : "Technology" 
    }, { 
    "target" : 1, 
    "source" : 0, 
    "relation" : "Trainee" 
    }, { 
    "target" : 2, 
    "source" : 0, 
    "relation" : "Manager" 
    }, { 
    "target" : 3, 
    "source" : 0, 
    "relation" : "Technology" 
    }, { 
    "target" : 2, 
    "source" : 4, 
    "relation" : "Expert" 
    }, { 
    "target" : 2, 
    "source" : 5, 
    "relation" : "Expert" 
    }, { 
    "target" : 1, 
    "source" : 5, 
    "relation" : "Expert" 
    }, { 
    "target" : 6, 
    "source" : 5, 
    "relation" : "Trainee" 
    }, { 
    "target" : 7, 
    "source" : 5, 
    "relation" : "Technology;New Firm" 
    }, { 
    "target" : 8, 
    "source" : 4, 
    "relation" : "Expert" 
    }, { 
    "target" : 9, 
    "source" : 4, 
    "relation" : "New Firm" 
    }, { 
    "target" : 8, 
    "source" : 4, 
    "relation" : "Expert" 
    }, { 
    "target" : 9, 
    "source" : 4, 
    "relation" : "New Firm" 
    }, { 
    "target" : 6, 
    "source" : 5, 
    "relation" : "Trainee" 
    }, { 
    "target" : 7, 
    "source" : 5, 
    "relation" : "Technology;New Firm" 
    } ] 
}; 
+0

唯一W¯¯唉任何人都可以幫助你看到你的代碼... –

+0

sry,我剛剛用我的代碼集更新了這個問題。我已經嘗試基於D3版本4功能修改它,但我無法準確地使其工作。目前,節點和文本是重疊的。我無法在節點之間提供固定鏈接/邊緣長度,我可以使用v3 linkDistance函數提供這些長度。 – VarunC

+0

我試圖按照這個例子 - http://bl.ocks.org/mbostock/2675ff61ea5e063ede2b5d63c08020c7,我不能以兩個邊緣之間爲中心我的圖像節點。目前,圖像放置從邊緣/鏈接開始。 – VarunC

回答

5

你問的問題亂舞一下子,讓我們得到一點小san get在這個問題上。

首先,linkDistance現在distance是在d3.forceLink,所以在你的代碼:

.force("link", d3.forceLink().id(function(d) { return d.id; }).distance(200)) 

其次,居中你的形象,這樣當您設置它的x位置:

node 
    .attr("x", function(d) { 
    return (d.x - img_w /2); 
    }); 

第三,要進行邊界檢測,您需要自己實現這一點。例如,爲了解決這個節點位置將是(對最後的代碼片斷建築):

node 
    .attr("x", function(d) { 
    var xPos = (d.x - img_w /2); 
    if (xPos < 0) return 0; 
    if (xPos > (960 - img_w)) return (960 - img_w); 
    return xPos; 
    }) 
    .attr("y", function(d) { 
    var yPos = d.y; 
    if (yPos < 0) return 0; 
    if (yPos > (600 - img_h)) return (600 - img_h); 
    return yPos; 
    }); 

現在,同樣的方法適用於鏈接...


下面是一些示例代碼,我」 VE開始實施一些修正:

<!DOCTYPE html> 
 
<html> 
 

 
<head> 
 
    <script data-require="[email protected]" data-semver="4.0.0" src="https://d3js.org/d3.v4.min.js"></script> 
 
    <style> 
 
    .links line { 
 
     stroke: #aaa; 
 
    } 
 
    
 
    .nodes circle { 
 
     pointer-events: all; 
 
     stroke: none; 
 
     stroke-width: 40px; 
 
    } 
 
    </style> 
 
</head> 
 

 
<body> 
 
    <svg width="960" height="600"></svg> 
 
    <script> 
 
    var root = { 
 
     "nodes": [{ 
 
     "subname": "", 
 
     "name": "Telco Power Case", 
 
     "image": "http://lorempixel.com/24/24/", 
 
     "id": 0 
 
     }, { 
 
     "subname": "Contact", 
 
     "name": "Suman Kumar", 
 
     "image": "http://lorempixel.com/24/24/", 
 
     "id": 1 
 
     }, { 
 
     "subname": "Contact", 
 
     "name": "Karla Samuel", 
 
     "image": "http://lorempixel.com/24/24/", 
 
     "id": 2 
 
     }, { 
 
     "subname": "Account", 
 
     "name": "Signa Tech", 
 
     "image": "http://lorempixel.com/24/24/", 
 
     "id": 3 
 
     }, { 
 
     "subname": "", 
 
     "name": "Maven's Case", 
 
     "image": "http://lorempixel.com/24/24/", 
 
     "id": 4 
 
     }, { 
 
     "subname": "", 
 
     "name": "Delta Case", 
 
     "image": "http://lorempixel.com/24/24/", 
 
     "id": 5 
 
     }, { 
 
     "subname": "Contact", 
 
     "name": "T Browney", 
 
     "image": "http://lorempixel.com/24/24/", 
 
     "id": 6 
 
     }, { 
 
     "subname": "Account", 
 
     "name": "Presto", 
 
     "image": "http://lorempixel.com/24/24/", 
 
     "id": 7 
 
     }, { 
 
     "subname": "Contact", 
 
     "name": "Bob Tannenbaum", 
 
     "image": "http://lorempixel.com/24/24/", 
 
     "id": 8 
 
     }, { 
 
     "subname": "Account", 
 
     "name": "Tesla Power", 
 
     "image": "http://lorempixel.com/24/24/", 
 
     "id": 9 
 
     }], 
 
     "links": [{ 
 
     "target": 1, 
 
     "source": 0, 
 
     "relation": "Trainee" 
 
     }, { 
 
     "target": 2, 
 
     "source": 0, 
 
     "relation": "Manager" 
 
     }, { 
 
     "target": 3, 
 
     "source": 0, 
 
     "relation": "Technology" 
 
     }, { 
 
     "target": 1, 
 
     "source": 0, 
 
     "relation": "Trainee" 
 
     }, { 
 
     "target": 2, 
 
     "source": 0, 
 
     "relation": "Manager" 
 
     }, { 
 
     "target": 3, 
 
     "source": 0, 
 
     "relation": "Technology" 
 
     }, { 
 
     "target": 2, 
 
     "source": 4, 
 
     "relation": "Expert" 
 
     }, { 
 
     "target": 2, 
 
     "source": 5, 
 
     "relation": "Expert" 
 
     }, { 
 
     "target": 1, 
 
     "source": 5, 
 
     "relation": "Expert" 
 
     }, { 
 
     "target": 6, 
 
     "source": 5, 
 
     "relation": "Trainee" 
 
     }, { 
 
     "target": 7, 
 
     "source": 5, 
 
     "relation": "Technology;New Firm" 
 
     }, { 
 
     "target": 8, 
 
     "source": 4, 
 
     "relation": "Expert" 
 
     }, { 
 
     "target": 9, 
 
     "source": 4, 
 
     "relation": "New Firm" 
 
     }, { 
 
     "target": 8, 
 
     "source": 4, 
 
     "relation": "Expert" 
 
     }, { 
 
     "target": 9, 
 
     "source": 4, 
 
     "relation": "New Firm" 
 
     }, { 
 
     "target": 6, 
 
     "source": 5, 
 
     "relation": "Trainee" 
 
     }, { 
 
     "target": 7, 
 
     "source": 5, 
 
     "relation": "Technology;New Firm" 
 
     }] 
 
    }; 
 

 
    var svg = d3.select("svg"), 
 
     width = +svg.attr("width"), 
 
     height = +svg.attr("height"); 
 

 
    var graph = root; 
 

 
    var w = window, 
 
     d = document, 
 
     e = d.documentElement, 
 
     g = d.getElementsByTagName('body')[0], 
 
     x = w.innerWidth || e.clientWidth || g.clientWidth, 
 
     y = w.innerHeight || e.clientHeight || g.clientHeight; 
 

 
    var realWidth = width; 
 
    var width = x; 
 
    var height = y; 
 
    var img_w = 24; 
 
    var img_h = 24; 
 
    var k = Math.sqrt(root.nodes.length/(width * height)); 
 

 
    var simulation = d3.forceSimulation() 
 
     .force("link", d3.forceLink().id(function(d) { 
 
     return d.id; 
 
     }).distance(200)) 
 
     .force("charge", d3.forceManyBody().strength(-5/k)) 
 
     .force("center", d3.forceCenter(width/2, height/2)); 
 

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

 
    var node = svg.append("g") 
 
     .attr("class", "nodes") 
 
     .selectAll("circle") 
 
     .data(graph.nodes) 
 
     .enter().append("image") 
 
     .attr("width", img_w) 
 
     .attr("height", img_h) 
 
     .attr("xlink:href", function(d) { 
 
     return d.image; 
 
     }) 
 
     .call(d3.drag() 
 
     .on("start", dragstarted) 
 
     .on("drag", dragged) 
 
     .on("end", dragended)); 
 

 
    var links_text = svg.selectAll(".linetext") 
 
     .data(graph.links) 
 
     .enter() 
 
     .append("text") 
 
     .attr("class", "linetext slds-text-heading--small") 
 
     .attr("text-anchor", "middle") 
 
     .text(function(d) { 
 
     return '[' + d.relation + ']'; 
 
     }); 
 

 
    var nodes_text = svg.selectAll(".nodetext") 
 
     .data(graph.nodes) 
 
     .enter() 
 
     .append("text") 
 
     .attr("class", "nodetext slds-text-heading--label") 
 
     .attr("text-anchor", "middle") 
 
     .attr("dx", -20) 
 
     .attr("dy", 20) 
 
     .text(function(d) { 
 
     return (d.subname != '' ? (d.subname + ': ') : '') + d.name; 
 
     }); 
 

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

 
    simulation.force("link") 
 
     .links(graph.links); 
 

 
    function ticked() { 
 
     link 
 
     .attr("x1", function(d) { 
 
      var xPos = d.source.x; 
 
      if (xPos < 0) return 0; 
 
      if (xPos > (960 - img_w)) return (960 - img_w); 
 
      return xPos; 
 
     }) 
 
     .attr("y1", function(d) { 
 
      var yPos = d.source.y; 
 
      if (yPos < 0) return 0; 
 
      if (yPos > (600 - img_h)) return (600 - img_h); 
 
      return yPos; 
 
     }) 
 
     .attr("x2", function(d) { 
 
      var xPos = d.target.x; 
 
      if (xPos < 0) return 0; 
 
      if (xPos > (960 - img_w)) return (960 - img_w); 
 
      return xPos; 
 
     }) 
 
     .attr("y2", function(d) { 
 
      var yPos = d.target.y; 
 
      if (yPos < 0) return 0; 
 
      if (yPos > (600 - img_h)) return (600 - img_h); 
 
      return yPos; 
 
     }); 
 

 
     links_text 
 
     .attr("x", function(d) { 
 
      var xPos = (d.source.x + d.target.x)/2; 
 
      if (xPos < 0) return 0; 
 
      if (xPos > (960 - img_w)) return (960 - img_w); 
 
      return xPos; 
 
     }) 
 
     .attr("y", function(d) { 
 
      var yPos = (d.source.y + d.target.y)/2; 
 
      if (yPos < 0) return 0; 
 
      if (yPos > (600 - img_h)) return (600 - img_h); 
 
      return yPos; 
 
     }); 
 

 

 
     node 
 
     .attr("x", function(d) { 
 
      var xPos = (d.x - img_w /2); 
 
      if (xPos < 0) return 0; 
 
      if (xPos > (960 - img_w)) return (960 - img_w); 
 
      return xPos; 
 
     }) 
 
     .attr("y", function(d) { 
 
      var yPos = d.y; 
 
      if (yPos < 0) return 0; 
 
      if (yPos > (600 - img_h)) return (600 - img_h); 
 
      return yPos; 
 
     }); 
 

 
     nodes_text 
 
     .attr("x", function(d) { 
 
      return d.x + 20 
 
     }) 
 
     .attr("y", function(d) { 
 
      return d.y + img_w/2; 
 
     }); 
 
    } 
 

 

 
    function dragstarted(d) { 
 
     if (!d3.event.active) simulation.alphaTarget(0.3).restart(); 
 
     d.fx = d.x; 
 
     d.fy = d.y; 
 
    } 
 

 
    function dragged(d) { 
 
     d.fx = d3.event.x; 
 
     d.fy = d3.event.y; 
 
    } 
 

 
    function dragended(d) { 
 
     if (!d3.event.active) simulation.alphaTarget(0); 
 
     d.fx = null; 
 
     d.fy = null; 
 
    } 
 
    </script> 
 
</body> 
 

 
</html>

+0

謝謝@Mark,你一直非常有幫助。我可以讓你的建議變化看起來很不錯。我甚至在背景上添加了一個White Rect背景,以便使標籤不會被它們之間的鏈接覆蓋。我向你尋求的最後一條建議是,我們可以引入一個函數來檢測標籤(節點文本/鏈接文本)是否相互重疊? – VarunC

+0

我還沒有嘗試過像這樣實現標籤,但[此塊](http://bl.ocks.org/MoritzStefaner/1377729)可能是你想要的。 – ropeladder