强制定向图上的d3.js工具提示在悬停在链接上时不显示完整数据

时间:2016-12-21 01:11:18

标签: javascript d3.js

以下是 JSON数据

var IDData = JSON.stringify([
  ["C2", "ID2", "Customer", "ID_Card", "2015-1-1", "2015-1-1", 500.0, 2],
  ["C2", "ID2", "Customer", "ID_Card", "2015-1-1", "2015-1-1", 700.0, 3],
  ["C2", "C3", "Customer", "Customer", "2015-1-1", "2015-1-1", 500.0, 2],
  ["C2", "C3", "Customer", "Customer", "2015-1-2", "2015-1-3", 600.0, 2],
  ["C6", "C1", "Customer", "Customer", "2015-1-1", "2015-1-1", 500.0, 1],
  ["C5", "ID4", "Customer", "ID_Card", "2015-1-1", "2015-1-1", 500.0, 2],
  ["C1", "ID1", "Customer", "ID_Card", "2015-1-1", "2015-1-1", 500.0, 1],
  ["C1", "P1", "Customer", "Phone", "2015-1-1", "2015-1-1", 500.0, 1],
  ["C6", "P2", "Customer", "Phone", "2015-1-1", "2015-1-1", 500.0, 2],
  ["C6", "P2", "Customer", "Phone", "2015-1-3", "2015-1-4", 800.0, 2],

  ["C2", "C6", "Customer", "Customer", "2015-1-1", "2015-1-1", 500.0, 1],
  ["C4", "C3", "Customer", "Customer", "2015-1-1", "2015-1-1", 500.0, 3],
  ["C1", "C2", "Customer", "Customer", '2015-1-1', "2015-1-1", 500.0, 1],
  ["C4", "ID3", "Customer", "ID_Card", "2015-1-1", "2015-1-1", 500.0, 3],
  ["C3", "ID3", "Customer", "ID_Card", "2015-1-1", "2015-1-1", 500.0, 3],
  ["C1", "C5", "Customer", "Customer", "2015-1-1", "2015-1-1", 500.0, 1]
]);

我正在迭代这个JSON数据,把它变成一个适合制作图形的格式,如下所示:

         var galData = JSON.parse(IDData);
var startnodes = [];
var endnodes = [];
var startnodetype = [];
var endnodetype = [];
var SendTime = [];
var PayTime = [];
var Total_Amt = [];
var Depth = [];
galData.map(function(e, i) {
  startnodes.push(e[0]);
  endnodes.push(e[1]);
  startnodetype.push(e[2]);
  endnodetype.push(e[3]);
  SendTime.push(e[4]);
  PayTime.push(e[5]);
  Total_Amt.push(e[6]);
  Depth.push(e[7]);
});
var final_data = createNodes(startnodes, endnodes, startnodetype, endnodetype, SendTime, PayTime, Total_Amt, Depth);
makeGraph("#Network_graph", final_data);

createNodes()功能如下:

            function createNodes(startnodes, endnodes, startnodetype, endnodetype, SendTime, PayTime, Total_Amt, Depth) {
  var node_set = [];
  var links = [];
  var nodetype = d3.set();
  startnodes.forEach(function(src, i) {
    var tgt = endnodes[i];
    if (!node_set.find(function(d) {
        return d.id == src
      })) {
      node_set.push({
        id: src,
        type: startnodetype[i]
      });
    }
    if (!node_set.find(function(d) {
        return d.id == tgt
      })) {
      node_set.push({
        id: tgt,
        type: endnodetype[i]
      });
    }

    links.push({
      source: src,
      target: tgt,
      sendtime: SendTime[i],
      paytime: PayTime[i],
      total_amt: Total_Amt[i],
      depth: Depth[i],
      value: 1
    });
  });

  startnodetype.forEach(function(src, i) {
    var tgt_type = endnodetype[i];
    nodetype.add(src);
    nodetype.add(tgt_type);
  });

  var d3GraphData = {
    nodes: node_set.map(function(d) {
      return {
        id: d.id,
        type: d.type,
        group: 1
      }
    }),
    links: links,
    nodetype: nodetype.values().map(function(d) {
      return {
        id: d.id,
        group: 1
      }
    })
  }
  return d3GraphData;

};

在我的 makeGraph()函数中,我可以使用工具提示将鼠标悬停在节点和链接上时显示文字:

我显示

   nodes: d.id and d.type,
   links: d.paytime,d.Sendtime,d.Amount and d.depth

以下是代码:

     var tooltip = d3.select("body")
      .append("div")
      .attr("class", "tooltip")
      .style("opacity", 0);


       var link = svg.append("g")
    .attr("class", "links")
    .selectAll("line")
    .data(d3GraphData.links)
    .enter().append("line")
    .attr("stroke-width", function(d) {
      return Math.sqrt(d.value);
    })
    .on('mouseover', function(d) {
      tooltip.transition()
        .duration(300)
        .style("opacity", .8);
      tooltip.html("<p/>Paytime:" + d.paytime + "<p/>Amount:" + d.total_amt + "<p/>SendTime:" + d.sendtime + "<p/>Depth" + d.depth)

      .style("left", (d3.event.pageX) + "px")
        .style("top", (d3.event.pageY + 10) + "px");
    })
    .on("mouseout", function() {
      tooltip.transition()
        .duration(100)
        .style("opacity", 0);
    })
    .on("mousemove", function() {
      tooltip.style("left", (d3.event.pageX) + "px")
        .style("top", (d3.event.pageY + 10) + "px");
    });

  var node = svg.append("g")
    .attr("class", "nodes")
    .selectAll("circle")
    .data(d3GraphData.nodes)
    .enter().append("circle")
    .attr("r", 5)
    .attr("fill", function(d) {
      return color(d.type);
    })
    .on('mouseover', function(d) {
      tooltip.transition()
        .duration(300)
        .style("opacity", .8);
      tooltip.html(d.id + "<p/>type:" + d.type)
        .style("left", (d3.event.pageX) + "px")
        .style("top", (d3.event.pageY + 10) + "px");
    })
    .on("mouseout", function() {
      tooltip.transition()
        .duration(100)
        .style("opacity", 0);
    })
    .on("mousemove", function() {
      tooltip.style("left", (d3.event.pageX) + "px")
        .style("top", (d3.event.pageY + 10) + "px");
    })

此代码工作正常,并在将鼠标悬停在链接上时显示文字。

但考虑到这种情况:

["C2", "ID2", "Customer", "ID_Card", "2015-1-1", "2015-1-1", 500.0, 2],
   ["C2", "ID2", "Customer", "ID_Card", "2015-1-2", "2015-1-3", 700.0, 2]

此处节点“C2”和“ID2”之间有2个交互,但是在将鼠标悬停在链接上时,工具提示会显示以下内容:

  PayTime: 2015-1-3
  Amount: 700
  SendTime: 2015-1-2
  Depth: 3

理想情况下,我希望它显示如下内容:以便捕获它们之间的交互数据。

  PayTime: 2015-1-3
  Amount: 700
  SendTime: 2015-1-2
  Depth: 3

   PayTime: 2015-1-1
  Amount: 500
  SendTime: 2015-1-1
  Depth: 2

以下是fiddle

的链接

1 个答案:

答案 0 :(得分:1)

如果你检查你的力图表,你会看到,对于你提到的那个特定链接(C2到ID2),你有两个行。当您将鼠标悬停在链接上时,您只会获得有关顶部行(触发鼠标悬停的行)的信息。

有一个解决方案。在鼠标悬停(或鼠标移动,无关紧要)内,创建一个函数,使所有有关这两个节点(源和目标)的数据。这是功能:

.on('mouseover', function(d) {
            var thisSource = d.source.id,
                thisTarget = d.target.id;
            var filteredLinks = d3GraphData.links.filter(function(e) {
                return (e.source.id === thisSource && e.target.id === thisTarget) 
                    || (e.source.id === thisTarget && e.target.id === thisSource);
            });

此函数创建一个名为filteredLinks的新数组,其中包含您需要的所有数据。例如,如果将鼠标悬停在您提到的链接上,则会得到结果:

[{
    "source": {
        "id": "C2",
        "type": "Customer",
        "group": 1,
        "index": 0,
        "x": 405.82425848083665,
        "y": 335.62277280058106,
        "vy": -0.0002356554712780902,
        "vx": 0.00011724088097396833
    },
    "target": {
        "id": "ID2",
        "type": "ID_Card",
        "group": 1,
        "index": 1,
        "x": 387.34926064098437,
        "y": 307.0409186320801,
        "vy": -0.000681439057517941,
        "vx": 0.0008168234236215556
    },
    "sendtime": "2015-1-1",
    "paytime": "2015-1-1",
    "total_amt": 500,
    "depth": 2,
    "value": 1,
    "index": 0
}, {
    "source": {
        "id": "C2",
        "type": "Customer",
        "group": 1,
        "index": 0,
        "x": 405.82425848083665,
        "y": 335.62277280058106,
        "vy": -0.0002356554712780902,
        "vx": 0.00011724088097396833
    },
    "target": {
        "id": "ID2",
        "type": "ID_Card",
        "group": 1,
        "index": 1,
        "x": 387.34926064098437,
        "y": 307.0409186320801,
        "vy": -0.000681439057517941,
        "vx": 0.0008168234236215556
    },
    "sendtime": "2015-1-2",
    "paytime": "2015-1-3",
    "total_amt": 700,
    "depth": 3,
    "value": 1,
    "index": 1
}]

现在,只需使用过滤后的数组填充工具提示即可。由于这是很多的工作,我会把那部分留给你......

PS:然而,最佳解决方案是首先有两条重叠的线条。为了解决这个问题,您可以在绘制图表之前在链接数组中搜索重复项并合并它们。