2013-11-27 49 views
4

我想要關注此D3 Javascript鏈接:>http://bl.ocks.org/mbostock/1093130以瞭解點擊事件是如何工作的。不幸的是,我無法完全理解整個代碼。我現在要做的是當點擊藍色節點時,其他兩個節點及其鏈接將顯示。當我再次點擊同一節點時,必須隱藏兩個節點及其鏈接。如果我點擊其他兩個節點之一,則不會發生任何事情。如何在點擊D3中的節點時顯示和隱藏鏈接和節點

這裏是JSON文件:

{ 
"nodes": [ 
    { 
     "name": "Node1", 
     "group": 2 
    }, 
    { 
     "name": "Node2", 
     "group": 1 
    }, 
    { 
     "name": "Node3", 
     "group": 1 
    } 
], 
"links": [ 
    { 
     "source": 0, 
     "target": 1, 
     "value": 2 
    }, 
    { 
     "source": 0, 
     "target": 2, 
     "value": 2 
    } 
] 
} 

這裏是我的代碼:

<!DOCTYPE html> 
<html> 
<head> 
<meta charset="UTF-8"> 
</head> 
<style> 

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

.link { 
stroke: #999; 
stroke-opacity: .6; 
} 

</style> 
<body> 
<p>Are you there!!!</p> 
<script type="text/javascript" src="d3/d3.v3.js"></script> 
<script> 

var width = 960, 
height = 500; 

d3.json("sample.json", function(error, graph) { 

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) 
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") 
.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; }); 
}); 
}); 
</script> 
</body> 
</html> 

任何人都可以請幫我解決這個問題吧。非常感謝您的幫助。

回答

10

可以打破切換上一個節點的鄰居的開/關的知名度所需的步驟/通過點擊節點的邊如下:

  1. 您需要根據來源的名稱類的鏈接/目標,並根據其名稱給出節點ID。這使得確定哪些節點/鏈接切換平凡。
  2. 您需要存儲每個節點是否當前「活動」,您可以使用它來確定是否應隱藏/顯示節點的鄰居。
  3. 您需要爲每個節點添加一個on("click", function(){ ... })

我創建了一個演示此方法的JSFiddle。突出的要點是:首先,我創建了一個字典到節點名稱映射到他們的鄰居的名字,這使得確定哪些鏈接顯示/隱藏容易:

// Set up dictionary of neighbors 
var node2neighbors = {}; 
for (var i =0; i < json.nodes.length; i++){ 
    var name = json.nodes[i].name; 
    node2neighbors[name] = json.links.filter(function(d){ 
      return d.source.name == name || d.target.name == name; 
     }).map(function(d){ 
      return d.source.name == name ? d.target.name : d.source.name; 
     }); 
} 

爲了得到鄰居的名字節點n,我首先篩選包含n的所有鏈接,然後在每個鏈接中提取不是n的節點的名稱。

接下來,這是您單擊節點時執行的邏輯。我使用節點陣列的跟蹤,我們要打開/關閉的節點(在OP說這種行爲應該只適用於在藍色節點"Node1"):

var clickableNodes = ["Node1"]; 
nodes.filter(function(n){ return clickableNodes.indexOf(n.name) != -1; }) 
     // Determine if current node's neighbors and their links are visible 
     var active = n.active ? false : true // toggle whether node is active 
     , newOpacity = active ? 0 : 1; 

     // Extract node's name and the names of its neighbors 
     var name  = n.name 
     , neighbors = node2neighbors[name]; 

     // Hide the neighbors and their links 
     for (var i = 0; i < neighbors.length; i++){ 
      d3.select("circle#" + neighbors[i]).style("opacity", newOpacity); 
      d3.selectAll("line." + neighbors[i]).style("opacity", newOpacity); 
     } 
     // Update whether or not the node is active 
     n.active = active; 
    }); 
+0

非常感謝您的回答。它正在工作。看來我需要深入瞭解你的代碼並有更多的理解。我是D3的新手。 – user2864315

+0

請再提一個問題。在代碼中使用過濾器和映射的原因是什麼?請你用幾句話向我解釋一下?我可以看到,如果你點擊其中一個節點,藍色的節點就會消失。任何想法爲什麼? – user2864315

+0

@ user2864315:是的,當你點擊任何節點時,代碼現在會隱藏鄰居和所有鄰居的鏈接。這是非常普遍的,所以如果你只想要一個特定節點的這種行爲,你可以很容易地添加一個'if'語句,以便它只適用於那個節點。另外,我會添加幾個句子來解釋'map'和'filter'。 – mdml