2013-08-29 23 views
8

我製作了一個有力的圖形,我想改變包含"entity":"company"的數據的節點形狀,以便它們具有矩形形狀,而沒有這部分數據的其他數據會像現在一樣是圓形的。D3力有向圖,根據數據和值給出不同的形狀?

你可以看到,只有圈的節點在這裏我的工作例如:http://jsfiddle.net/dzorz/uWtSk/

我試圖用if else語句添加矩形中的部分代碼,我追加形狀像這樣的節點:

function(d) 
    { 
     if (d.entity == "company") 
     { 
      node.append("rect") 
       .attr("class", function(d){ return "node type"+d.type}) 
       .attr("width", 100) 
       .attr("height", 50) 
       .call(force.drag); 
     } 
     else 
     { 
     node.append("circle") 
      .attr("class", function(d){ return "node type"+d.type}) 
      .attr("r", function(d) { return radius(d.value) || 10 }) 
      //.style("fill", function(d) { return fill(d.type); }) 
      .call(force.drag); 
     } 
    } 

但是在任何節點上我都沒有得到任何形狀。

什麼是設置此的正確方法?

整個代碼如下所示: 腳本:

var data = {"nodes":[ 
         {"name":"Action 4", "type":5, "slug": "", "value":265000}, 
         {"name":"Action 5", "type":6, "slug": "", "value":23000}, 
         {"name":"Action 3", "type":4, "slug": "", "value":115000}, 
         {"name":"Yahoo", "type":1, "slug": "www.yahoo.com", "entity":"company"}, 
         {"name":"Google", "type":1, "slug": "www.google.com", "entity":"company"}, 
         {"name":"Action 1", "type":2, "slug": "",}, 
         {"name":"Action 2", "type":3, "slug": "",}, 
         {"name":"Bing", "type":1, "slug": "www.bing.com", "entity":"company"}, 
         {"name":"Yandex", "type":1, "slug": "www.yandex.com)", "entity":"company"} 
        ], 
      "links":[ 
         {"source":0,"target":3,"value":10}, 
         {"source":4,"target":3,"value":1}, 
         {"source":1,"target":7,"value":10}, 
         {"source":2,"target":4,"value":10}, 
         {"source":4,"target":7,"value":1}, 
         {"source":4,"target":5,"value":10}, 
         {"source":4,"target":6,"value":10}, 
         {"source":8,"target":4,"value":1} 
         ] 
       }  



    var w = 560, 
     h = 500, 
     radius = d3.scale.log().domain([0, 312000]).range(["10", "50"]); 

    var vis = d3.select("body").append("svg:svg") 
     .attr("width", w) 
     .attr("height", h); 

     vis.append("defs").append("marker") 
     .attr("id", "arrowhead") 
     .attr("refX", 17 + 3) /*must be smarter way to calculate shift*/ 
     .attr("refY", 2) 
     .attr("markerWidth", 6) 
     .attr("markerHeight", 4) 
     .attr("orient", "auto") 
     .append("path") 
      .attr("d", "M 0,0 V 4 L6,2 Z"); //this is actual shape for arrowhead 

    //d3.json(data, function(json) { 
     var force = self.force = d3.layout.force() 
      .nodes(data.nodes) 
      .links(data.links) 
      .distance(100) 
      .charge(-1000) 
      .size([w, h]) 
      .start(); 



     var link = vis.selectAll("line.link") 
      .data(data.links) 
      .enter().append("svg:line") 
      .attr("class", function (d) { return "link" + d.value +""; }) 
      .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; }) 
      .attr("marker-end", function(d) { 
               if (d.value == 1) {return "url(#arrowhead)"} 
               else { return " " } 
              ;}); 


     function openLink() { 
     return function(d) { 
      var url = ""; 
      if(d.slug != "") { 
       url = d.slug 
      } //else if(d.type == 2) { 
       //url = "clients/" + d.slug 
      //} else if(d.type == 3) { 
       //url = "agencies/" + d.slug 
      //} 
      window.open("//"+url) 
     } 
    } 




     var node = vis.selectAll("g.node") 
      .data(data.nodes) 
      .enter().append("svg:g") 
      .attr("class", "node") 
      .call(force.drag); 

     node.append("circle") 
      .attr("class", function(d){ return "node type"+d.type}) 
      .attr("r", function(d) { return radius(d.value) || 10 }) 
      //.style("fill", function(d) { return fill(d.type); }) 
      .call(force.drag); 

     node.append("svg:image") 
      .attr("class", "circle") 
      .attr("xlink:href", function(d){ return d.img_href}) 
      .attr("x", "-16px") 
      .attr("y", "-16px") 
      .attr("width", "32px") 
      .attr("height", "32px") 
      .on("click", openLink()); 

     node.append("svg:text") 
      .attr("class", "nodetext") 
      .attr("dx", 0) 
      .attr("dy", ".35em") 
      .attr("text-anchor", "middle") 
      .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("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); 
     }); 
    //});  

CSS:

.link10 { stroke: #ccc; stroke-width: 3px; stroke-dasharray: 3, 3; } 
.link1 { stroke: #000; stroke-width: 3px;} 
.nodetext { pointer-events: none; font: 10px sans-serif; } 

.node.type1 { 
    fill:brown; 
} 
.node.type2 { 
    fill:#337147; 
} 
.node.type3 { 
    fill:blue; 
} 
.node.type4 { 
    fill:red; 
} 

.node.type5 { 
    fill:#1BC9E0; 
} 

.node.type6 { 
    fill:#E01B98; 
} 

image.circle { 
    cursor:pointer; 
} 

您可以編輯自己的jsfiddle的帖子開頭的鏈接...

+0

您似乎沒有使用代碼來更改jsfiddle中的形狀。你能發表一個能證明問題的人嗎? –

+0

我已經發布了有問題的代碼,如果上面的else語句(請參見第一代碼塊)...在jsfiddle中,我已經刪除了這個語句,所以你只能看到圓形 – dzordz

+0

這真的很重要,你把代碼放在哪裏以及你如何稱呼它。 –

回答

6

這裏的解決方案:http://jsfiddle.net/Bull/4btFx/1/

我得到這個工作通過向每個節點添加一個類,然後使用「selectAll」爲每個類添加形狀。在下面的代碼中,我添加了一個類「節點」和由我的JSON(d.type)返回的「rect」或「ellipse」類。

var node = container.append("g") 
    .attr("class", "nodes") 
    .selectAll(".node") 
    .data(graph.nodes) 
    .enter().append("g") 
    .attr("class", function(d) { 
    return d.type + " node"; 
    }) 
    .call(drag); 

那麼你可以添加形狀爲每個類的所有元素:

d3.selectAll(".rect").append("rect") 
    .attr("width", window.nodeWidth) 
    .attr("height", window.nodeHeight) 
    .attr("class", function(d) { 
    return "color_" + d.class 
    }); 

    d3.selectAll(".ellipse").append("rect") 
    .attr("rx", window.nodeWidth*0.5) 
    .attr("ry", window.nodeHeight*0.5) 
    .attr("width", window.nodeWidth) 
    .attr("height", window.nodeHeight) 
    .attr("class", function(d) { 
    return "color_" + d.class 
    }); 

在上面的例子中,我使用半徑爲矩形繪製橢圓,因爲它集中他們的方式一樣矩形。但它也適用於其他形狀。在我連接的jsfiddle中,居中關閉,但形狀正確。

0

我使用我從Filtering in d3.js on bl.ocks.org蒐集的filter方法實現了此行爲。

initGraphNodeShapes() { 
    let t = this; 

    let graphNodeCircles = 
    t.graphNodesEnter 
     .filter(d => d.shape === "circle") 
     .append("circle") 
     .attr("r", 15) 
     .attr("fill", "green"); 

    let graphNodeRects = 
    t.graphNodesEnter 
     .filter(d => d.shape === "rect") 
     .append("rect") 
     .attr("width", 20) 
     .attr("height", 10) 
     .attr("x", -10) // -1/2 * width 
     .attr("y", -5) // -1/2 * height 
     .attr("fill", "blue"); 

    return graphNodeCircles.merge(graphNodeRects); 
} 

我有這個initGraphNodeShapes電話裏面,因爲我的代碼是比較大的和重構。 t.graphNodesEnter是數據加入enter()在別處調用後的數據選擇的參考。如果你需要更多的上下文,請平息我另外,我使用d => ...版本,因爲我使用的是啓用lambdas的ES6。如果您使用的是ES6之前版本,那麼您必須將其更改爲function(d)...表單。