2016-11-29 327 views
1

我已經在堆棧中查看了各種鏈接距離,並且似乎爲了改變鏈接距離,您需要實現一個函數,然後通過它來動態分配鏈接距離,如下所示:d3.forcesimulation()鏈接距離

function linkDistance(d) { 
    return d.distance; 
} 

然後我想我應該能夠傳遞到SVG而是返回使用.linkDistance從函數的文檔不存在linkdistance或距離

var link = svg.selectAll(".link") 
    .data(bilinks)  
    .enter().append("path") 
    .style("stroke", "#6b7071") //gunmetal grey link 
    .attr("class", "link") 
    .linkDistance(linkDistance) 
    .attr("fill", "none") 

的錯誤:https://github.com/d3/d3/blob/master/API.md#forces-d3-force理想我想喜歡修改fy參數(如鏈接距離,電荷,力和鏈接顏色)使用的數據非常類似於我對點的顏色所做的事情,但是,我相信我缺乏如何正確執行此操作的知識。例如在最後一行代碼,如果我是改變從:到

.style("stroke", "#6b7071") //gunmetal grey link 

.style("stroke", function(d) { return color(d.group);}) 

的鏈接的顏色是一種顏色VS 39點的顏色我將根據該組預料。 更進一步,我還試圖

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

UPDATE: 我unsured,對於長度的數據是數組鏈接和bilinks使我能引用的距離在但是不能似乎使用了的值然而陣列顯示的console.log它被正確地存儲JSON文檔的

CODE

<!DOCTYPE html> 
<meta charset="utf-8"> 
<style> 

.node { 
    stroke: #fff; 
    stroke-width: 1.5px; 
} 



</style> 
<svg width="15000" height="15000"></svg> 
<script src="https://d3js.org/d3.v4.min.js"></script> 
<script> 

//change background color to black 
backgroundColor = d3.rgb('#000000') 
d3.select("body").style("background-color", backgroundColor) 

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

//var color = d3.scaleOrdinal(d3.schemeCategory20); 

var simulation = d3.forceSimulation() 
    .force("link", d3.forceLink().distance(500).strength(0.1)) 
    .force("charge", d3.forceManyBody()) 
    .force("center", d3.forceCenter(width/2, height/2)); 


d3.json("hc7data.json", function(error, graph) { 
    if (error) throw error; 


    var nodes = graph.nodes, 
     nodeById = d3.map(nodes, function(d) { return d.id; }), 
     links = graph.links, 
     bilinks = []; 


//get graphics to make color scale us scaleOrdinal if every color chosen 
    var color = d3.scaleOrdinal() 
     .domain([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40]) 
     .range(["#af1f45", "#be4f5e","#cd767c","#dc9d9e","#ecc9c8","#fbdbe9","#f7bbd5","#f49ac1","#f179ae","#ef509c", 
     "#e3d4e4","#cdb1cf","#9a5699","#b990ba", "#a973a9","#d6eaf3","#b0daeb","#8acce4","#5ebfde","#00a5db","#6dbe46","#e0efd4", 
     "#c3e0ae","#a7d48b","#8cc866","#fff2d1","#ffe8a8","#ffdf80","#ffd751","#fecf07","#fee1c9","#fcc79c","#faae74","#f69d58", 
     "#f7964a","#fde3d9","#fcccbc","#f58870","#f9b4a0","#f79e87"]); 


    links.forEach(function(link) { 
    var s = link.source = nodeById.get(link.source), 
     t = link.target = nodeById.get(link.target), 
     i = {}, // intermediate node 
     linkDist = link.distance; 
    nodes.push(i); 
    //console.log(linkDist); 
    links.push({source: s, target: i, linkDist:linkDist}, {source: i, target: t, linkDist:linkDist }); 
    bilinks.push([s, i, t,linkDist]); 
    }); 

    var link = svg.selectAll(".link") 
    .data(bilinks) 
    .enter().append("path") 
    .style("stroke", "#6b7071") //gunmetal grey 
    .attr("class", "link") 
    .attr("fill", "none") 



    var node = svg.selectAll(".node") 
    .data(nodes.filter(function(d) { return d.id; })) 
    .enter().append("circle") 
     .attr("class", "node") 
     //change circle size according to new function 
     .attr("r", function(d) {return d.size}) 
     .attr("fill", function(d) { return color(d.group); }) 
     .style("stroke", "#000000") 
     //.style("stroke", function(d) { return color(d.group); }) 
     .call(d3.drag() 
      .on("start", dragstarted) 
      .on("drag", dragged) 
      .on("end", dragended)); 

    node.append("title") 
     .text(function(d) { return d.id; }); 

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

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

    function ticked() { 
    link.attr("d", positionLink); 
    node.attr("transform", positionNode); 
    } 
}); 




function positionLink(d) { 
    return "M" + d[0].x + "," + d[0].y 
     + "S" + d[1].x + "," + d[1].y 
     + " " + d[2].x + "," + d[2].y; 
} 

function positionNode(d) { 
    return "translate(" + d.x + "," + d.y + ")"; 
} 

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> 

樣品

{ 
    "nodes": [ 
    { 
    "id": "test1", 
    "group": 1, 
    "size": 10 
    }, 
    { 
    "id": "test2", 
    "group": 1, 
    "size": 10 
    } 
    ], 
    "links": [ 
    { 
    "source": "test1", 
    "target": "test2", 
    "value": 1, 
    "distance": 5 
    }, 
    { 
    "source": "test2", 
    "target": "test1", 
    "value": 1, 
    "distance": 5 
    } 
    ] 
} 

回答

1

我相信你是幾乎沒有。使用像function(d) {return d.distance}這樣的自定義函數是正確的方法。但是,您不需要在鏈接數組中推送額外的信息,因爲鏈接已包含JSON文件的屬性。

至於你提到的仿真可以聲明如下使用距離屬性:

var simulation = d3.forceSimulation() 
    .force("link", d3.forceLink().distance(function(d) {return d.distance;}).strength(0.1)) 

,這是沒有必要推額外的信息,鏈接陣列,這樣你就可以刪除此行:

links.push({source: s, target: i, linkDist:linkDist}, {source: i, target: t, linkDist:linkDist }); 

我創建了一個帶有一些修改的JSON的JSFiddle來顯示結果here。我添加了一個額外的鏈接到另一個距離較短的節點來顯示效果。

+0

d3.v4.min.js:3錯誤:屬性d:預期編號「MNaN,NaNSNaN,NaN ...」(匿名函數)@ d3.v4.min.js:3oy @ d3.v4.min .js:6uy @ d3.v4.min.js:6ticked @ HC7test.html:116call @ d3.v4.min.js:6n @ d3.v4.min.js:7Wn @ d3.v4.min.js:2 $ n @ d3.v4.min.js:2 7934d3.v4.min。js:3錯誤:屬性轉換:期望的編號,「當我運行你的代碼時,我得到的是translate(NaN,NaN),這可能是我插入的方式並引用我的json –

+0

這當然是可能的。 'links?{{source:s,target:i,linkDist:linkDist},{source:i,target:t,linkDist:linkDist});'line? – jobB

+0

'links'數組中的每一項都有一個距離屬性是一個數字? – jobB

0

你當然可以有鏈接的距離因鏈接而異。它只需要設置在一個稍有不同的地方。在你的情況,你鏈路距離設置爲500。相反,你會想要做這樣的事情:

var simulation = d3.forceSimulation() 
    .force("link", d3.forceLink().distance(linkDistance).strength(0.1)) 
    .force("charge", d3.forceManyBody()) 
    .force("center", d3.forceCenter(width/2, height/2)); 

function linkDistance(d) { 
    return d.distance; 
} 

https://github.com/d3/d3-force/blob/master/README.md#link_distance