2013-11-27 2 views
4

Я стараюсь следовать этой ссылке D3 Javascript:>http://bl.ocks.org/mbostock/1093130, чтобы понять, как работает клик. К сожалению, я не мог полностью понять все коды. То, что я пытаюсь сделать в данный момент, - это щелкнуть по синему узлу, отобразятся два других узла и их ссылки. Когда я снова нажимаю на тот же узел, два узла и их ссылки должны скрываться. Если я нажму на один из двух других узлов, ничего не должно произойти.Как отображать и скрывать ссылки и узлы при нажатии на узел в D3 Javascript

Вот файл в формате 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. Вы должны класс ссылок на основе имен источников/целей и дать идентификаторы узлов на основе их имен. Это позволяет определить, какие узлы/ссылки для переключения тривиальны.
  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 в каждой из этих ссылок.

Далее приведена логика, выполняемая при нажатии на узел. Я использую массив узлов для отслеживания узлов, которые мы хотим, чтобы переключить вкл/выкл (ОП сказал, что это поведение должно применяться только для синего узла "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', чтобы он применим только к одному узлу. Кроме того, я добавлю несколько предложений, объясняющих «карту» и «фильтр». – mdml

Смежные вопросы