定义要在工具提示中使用的JSON数据属性(工具提示显示"未定义")

时间:2017-05-25 22:22:21

标签: javascript json d3.js

我已经查看了与此问题相关的其他SO问题,实施了解决方案,并且尚未取得成功。

我有一个由外部JSON文件驱动的d3强制定向图,该文件有五个属性:source,target,source_title,target_title和value。

JSON示例:

[{"source":"Michael Scott", "source_title":"boss", "target":"Jim Halpert", "target_title":"salesman", "value":"1"},
{"source":"Pam Beasley", "source_title":"receptionist", "target":"Jim Halpert", "target_title":"salesman", "value":"1"},
{"source":"Pam Beasley", "source_title":"receptionist", "target":"Angela", "target_title":"accountant", "value":"1"}]

当前脚本:

<script>

d3.json("IA_Data.json", function(error, data){

data.forEach(function(d) {
        d.source_title = d.source_title;
    });

var links = data;

var nodes = {};

// Compute the distinct nodes from the links.
links.forEach(function(link) {
  link.source = nodes[link.source] || (nodes[link.source] = {name: link.source});
  link.target = nodes[link.target] || (nodes[link.target] = {name: link.target});
});

var width = 2000,
    height = 1000;

var force = d3.layout.force()
    .nodes(d3.values(nodes))
    .links(links)
    .size([width, height])
    .linkDistance(5)
    .charge(-400)
    .gravity(.2)
    .on("tick", tick)
    .start();

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

var path = svg.append("g").selectAll("path")
    .data(force.links())
  .enter().append("path")
    .attr("class", function(d) { return "link " + d.type; })
    .attr("marker-end", function(d) { return "url(#" + d.type + ")"; });

var tip = d3.tip()
          .attr('class', 'd3-tip')
          .offset([-10, 0])
          .html(function(d) {return d.source_title;});
svg.call(tip);

var circle = svg.append("g").selectAll("circle")
    .data(force.nodes())
    .enter().append("circle")
    .attr("r", 6)
    .on('mouseover', tip.show)
    .on('mouseout', tip.hide);

// Use elliptical arc path segments to doubly-encode directionality.
function tick() {
  path.attr("d", linkArc);
  circle.attr("transform", transform);
}

function linkArc(d) {
  var dx = d.target.x - d.source.x,
      dy = d.target.y - d.source.y,
      dr = Math.sqrt(dx * dx + dy * dy);
  return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
}

function transform(d) {
  return "translate(" + d.x + "," + d.y + ")";
}

});

</script>

如您所见,我正在尝试在d3.tip的.html行中返回value。我最初尝试初始化value的尝试在本节中:

data.forEach(function(d) {
        d.source_title = +d.source_title;
    });

生成的工具提示显示&#34; undefined&#34;,暗示source_title未正确定义。如果我在d3.tip中将source_title换成name,则source / target文字会显示在工具提示中。我该如何定义&#39; source_title&#39;属性正常吗?

非常感谢任何见解 - 谢谢!

1 个答案:

答案 0 :(得分:2)

节点数组中没有source_title

解决方案很简单:在填充节点数组时创建该键/值对:

links.forEach(function(link) {
    link.source = nodes[link.source] || (nodes[link.source] = {
        name: link.source,
        source_title: link.source_title//creating 'source_title' here
    });
});

以下是您的代码演示(注意:这里只有两个圆圈有标题):

var data = [{
  "source": "Michael Scott",
  "source_title": "boss",
  "target": "Jim Halpert",
  "target_title": "salesman",
  "value": "1"
}, {
  "source": "Pam Beasley",
  "source_title": "receptionist",
  "target": "Jim Halpert",
  "target_title": "salesman",
  "value": "1"
}, {
  "source": "Pam Beasley",
  "source_title": "receptionist",
  "target": "Angela",
  "target_title": "accountant",
  "value": "1"
}];

data.forEach(function(d) {
  d.source_title = d.source_title;
});

var links = data;

var nodes = {};

// Compute the distinct nodes from the links.
links.forEach(function(link) {
  link.source = nodes[link.source] || (nodes[link.source] = {
    name: link.source,
    source_title: link.source_title
  });
  link.target = nodes[link.target] || (nodes[link.target] = {
    name: link.target,
    target_title: link.target_title
  });
});

var width = 300,
  height = 150;

var force = d3.layout.force()
  .nodes(d3.values(nodes))
  .links(links)
  .size([width, height])
  .linkDistance(5)
  .charge(-400)
  .gravity(.2)
  .on("tick", tick)
  .start();

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

var path = svg.append("g").selectAll("ceciliaPayne")
  .data(force.links())
  .enter().append("path")
  .attr("class", function(d) {
    return "link " + d.type;
  })
  .attr("marker-end", function(d) {
    return "url(#" + d.type + ")";
  });

var tip = d3.tip()
  .attr('class', 'd3-tip')
  .offset([-10, 0])
  .html(function(d) {
    return d.source_title;
  });
svg.call(tip);

var circle = svg.append("g").selectAll("circle")
  .data(force.nodes())
  .enter().append("circle")
  .attr("r", 6)
  .on('mouseover', tip.show)
  .on('mouseout', tip.hide);

// Use elliptical arc path segments to doubly-encode directionality.
function tick() {
  path.attr("d", linkArc);
  circle.attr("transform", transform);
}

function linkArc(d) {
  var dx = d.target.x - d.source.x,
    dy = d.target.y - d.source.y,
    dr = Math.sqrt(dx * dx + dy * dy);
  return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
}

function transform(d) {
  return "translate(" + d.x + "," + d.y + ")";
}
path {
  fill: none;
  stroke: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-tip/0.7.1/d3-tip.min.js"></script>