Я работал с графиком с принудительной ориентацией, но я все еще плохо знаком с D3js и Javascript.

Я хочу, чтобы можно было щелкнуть узел и всплывающее окно с инфобоксом на странице и напечатать некоторую информацию об этом узле (из JSON).

Пример моего файла JSON:

{"directed": false, "graph": {}, 
"nodes": [{"id": 0, "name":"Ant" , "info":"Small Animal"}, 
{"id": 1 , "name":"Apple" , "info":"Fruit"}, 
{"id": 2 , "name":"Bat" , "info":"Fly Animal"}, 
{"id": 3 , "name":"Boat" , "info":"Vehicle"}, 
{"id": 4 , "name":"Banana" , "info":"Long cute Fruit"}, 
{"id": 5 , "name":"Cat" , "info":"Best Animal"}], 

"links": [{"source": 0, "target": 0 , "weight":1}, {"source": 0, "target": 2, "weight": 0.3}, 
{"source": 0, "target": 5, "weight":0.8}, {"source": 1, "target": 1, "weight":1}, 
{"source": 1, "target": 4, "weight":0.5}, {"source": 2, "target": 2, "weight":1}, 
{"source": 3, "target": 3, "weight":1}, {"source": 4, "target": 4, "weight":1}, 
{"source": 5, "target": 5, "weight":1}], 
"multigraph": false}

Поэтому, когда я нажимаю на узел. Должно появиться что-то вроде:

Name: Ant
Info: Small Animal
Connected to: Bat with 0.3 weight , Cat with 0.8 weight

Мой графовый код был во многом похож на пример силового направления, который я привел выше.

2
Lilbeartr 27 Май 2017 в 19:16

2 ответа

Лучший ответ

Вот быстрая реализация, она создает ваш «информационный блок» с использованием SVG:

  var tip;
  node.on("click", function(d){
    if (tip) tip.remove();

    tip  = svg.append("g")
      .attr("transform", "translate(" + d.x  + "," + d.y + ")");

    var rect = tip.append("rect")
      .style("fill", "white")
      .style("stroke", "steelblue");

    tip.append("text")
      .text("Name: " + d.name)
      .attr("dy", "1em")
      .attr("x", 5);

    tip.append("text")
      .text("Info: " + d.info)
      .attr("dy", "2em")
      .attr("x", 5);

    var con = graph.links
      .filter(function(d1){
        return d1.source.id === d.id;
      })
      .map(function(d1){
        return d1.target.name + " with weight " + d1.weight;
      })

    tip.append("text")
      .text("Connected to: " + con.join(","))
      .attr("dy", "3em")
      .attr("x", 5);

    var bbox = tip.node().getBBox();
    rect.attr("width", bbox.width + 5)
        .attr("height", bbox.height + 5)
  });

Запуск кода:

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

.links line {
  stroke: #999;
  stroke-opacity: 0.6;
}

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

text {
  font-family: sans-serif;
}

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

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().id(function(d) { return d.id; }))
    .force("charge", d3.forceManyBody())
    .force("center", d3.forceCenter(width / 2, height / 2));
    
d3.json("https://jsonblob.com/api/15daa79f-7573-11e8-b9d7-1b0997147957", function(error, graph) {
  if (error) throw error;
  
  link = svg.append("g")
      .attr("class", "links")
    .selectAll("line")
    .data(graph.links)
    .enter().append("line")
      .attr("stroke-width", function(d) { return d.weight * 3; });

  var node = svg.append("g")
      .attr("class", "nodes")
    .selectAll("circle")
    .data(graph.nodes)
    .enter().append("circle")
      .attr("r", 5)
      .attr("fill", function(d) { return color(d.group); })
      .call(d3.drag()
          .on("start", dragstarted)
          .on("drag", dragged)
          .on("end", dragended));

  var tip;
  svg.on("click", function(){
    if (tip) tip.remove();
  });
  node.on("click", function(d){
    d3.event.stopPropagation(); 
  
    if (tip) tip.remove();
    
    tip  = svg.append("g")
      .attr("transform", "translate(" + d.x  + "," + d.y + ")");
      
    var rect = tip.append("rect")
      .style("fill", "white")
      .style("stroke", "steelblue");
    
    tip.append("text")
      .text("Name: " + d.name)
      .attr("dy", "1em")
      .attr("x", 5);
      
    tip.append("text")
      .text("Info: " + d.info)
      .attr("dy", "2em")
      .attr("x", 5);

    var con = graph.links
      .filter(function(d1){
        return d1.source.id === d.id;
      })
      .map(function(d1){
        return d1.target.name + " with weight " + d1.weight;
      })
      
    tip.append("text")
      .text("Connected to: " + con.join(","))
      .attr("dy", "3em")
      .attr("x", 5);
    
    var bbox = tip.node().getBBox();
    rect.attr("width", bbox.width + 5)
        .attr("height", bbox.height + 5)
  });

  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; });

    node
        .attr("cx", function(d) { return d.x; })
        .attr("cy", function(d) { return 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>
3
Mark 21 Июн 2018 в 16:50

Вы можете добавить событие нажатия на узел, используя .on('click', function(d){ }); Например:

node.on("click", function(d){
      console.log(d);
       // here you can access data of node using d.key 
      alert("You clicked on node " + d.name);
    });
3
Dinesh undefined 27 Май 2017 в 16:28