如何将文本附加到 D3 工具提示?



我在将文本附加到 D3 工具提示时遇到问题。生成工具提示的代码会导致以下错误:

Uncaught TypeError: Cannot read property 'Name' of undefined

将显示工具提示,但没有任何文本。以下代码用于生成工具提示:

1.创建 .工具提示的代码

.toolTip {
position: absolute;
display: none;
min-width: 80px;
height: auto;
background: none repeat scroll 0 0 #ffffff;
border: 1px solid #6F257F;
padding: 14px;
text-align: center;

2.创建变量的代码。

var tooltip = d3.select("body")
.append("div")
.attr("class", "toolTip");
  1. 尝试追加到节点的代码

    // Nodes
    d3.select('svg g.nodes')
    .selectAll('circle.node')
    .data(root.descendants())
    .enter()
    .append('circle')
    .classed('node', true)
    .attr('cx', function(d) {return d.x;})
    .attr('cy', function(d) {return d.y;})
    .attr('r', 4)
    .on("mousemove", function(d){
    tooltip
    .style("left", d3.event.pageX - 50 +"px")
    .style("top", d3.event.pageY - 70 + "px")
    .style("display", "inline-block")
    .html(function (d) {return d.Name});
    })
    .on("mouseout", function(d){ tooltip.style("display", "none");});
    

让我们看一下在鼠标移动时调用的函数:

.on("mousemove", function(d){
tooltip
.style("left", d3.event.pageX - 50 +"px")
.style("top", d3.event.pageY - 70 + "px")
.style("display", "inline-block")
.html(function (d) {return d.Name});
})

在第一行中,函数中的d是指绑定到 svg 圆的基准面,而在这里:.html(function(d) {中,d是指绑定到工具提示的基准面。在这种情况下,两个d不是指同一件事。您没有任何数据绑定到工具提示,因此这不起作用 -d此处未定义,因此您的错误消息:"无法读取未定义的属性'名称'。

相反,只需使用圆的基准面:

.on("mousemove", function(d){
tooltip
.style("left", d3.event.pageX - 50 +"px")
.style("top", d3.event.pageY - 70 + "px")
.style("display", "inline-block")
.html(d.Name); 
})

每当您在 d3 选区的.html.attr方法中看到函数 (d) 时,您正在访问当前选区的每个元素的基准面。您不希望数据与工具提示相关联,因此无需在.html()方法中使用function(d),您已经在第一行中访问了所需的基准面。


看起来好像您正在使用 d3 分层布局。这将改变数据的结构,如果您从以下表单开始:

var data = { "name": "Parent", "children": [ 
{ "name": "Child A", "children": [ { "name": "Grandchild" } ] }, 
{ "name": "Child B", } 
] };

d3.hierarchy(data)将返回具有以下结构的数组:

[
{data: Object, height: number, depth: number, parent: null, children: array[number], x: number, y: number},
{data: Object, height: number, depth: number, parent: object, children: array[number], x: number, y: number},
... and so forth.
]

因此,对于要附加的每个节点,数据数组中都有一个元素(selection.data() 需要一个数组),并且传递给选择的数据中的每个项目都有一些属性,允许它正确定位、连接等。关键点是数据数组中的原始元素现在处于d.data。这与 d3.pie 或其他布局生成器相同 - 并避免属性名称之间(原始属性和布局创建的属性之间)之间的潜在重叠。

对你来说,主要的结果是你的名字不会驻留在d.Name,而是d.data.Name,因为这是由d3.hierarchy()创建的数据结构。

这是因为您没有任何数据绑定到工具提示。您的代码需要如下所示:

var t = d3.select("body")
.selectAll("div")
.data(<your data>)
.enter()
.append("div")
.attr("class", "toolTip");

现在,您的div 附加了要循环访问的数据。

最新更新