如何将文本附加到 D3 工具提示?
How to append text to D3 Tooltips?
我在将文本附加到 D3 工具提示时遇到问题。生成工具提示的代码导致以下错误:
Uncaught TypeError: Cannot read property 'Name' of undefined
工具提示显示,但没有任何文本。以下代码用于生成工具提示:
1.Code 创建 .toolTip 的位置
.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.Code 创建变量的位置。
var tooltip = d3.select("body")
.append("div")
.attr("class", "toolTip");
尝试附加到节点的代码
// 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");});
这是因为您没有任何与工具提示关联的数据。您的代码需要是这样的:
var t = d3.select("body")
.selectAll("div")
.data(<your data>)
.enter()
.append("div")
.attr("class", "toolTip");
现在您的 div 已附加数据以进行迭代。
让我们看一下mousemove调用的函数:
.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
指的是绑定在svg圆上的基准工具提示。在这种情况下,两个 d
指的不是同一件事。您没有任何数据绑定到工具提示,所以这将不起作用 - d
这里未定义,因此您的错误消息:"Cannot read property 'Name' of undefined."
相反,只需使用圆的基准:
.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
方法中看到 function(d) 时,您正在访问当前选择的每个元素的数据。你不想要与工具提示关联的数据,所以你不需要在 .html()
方法中使用 function(d)
,你已经在第一行访问了你想要的数据。
您似乎在使用 d3 分层布局。如果您以这样的形式开始,这将改变您的数据结构:
var data = { "name": "Parent", "children": [
{ "name": "Child A", "children": [ { "name": "Grandchild" } ] },
{ "name": "Child B", }
] };
d3.hierarchy(data)
将 return 具有以下结构的数组:
[
{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() 创建的数据结构。
我在将文本附加到 D3 工具提示时遇到问题。生成工具提示的代码导致以下错误:
Uncaught TypeError: Cannot read property 'Name' of undefined
工具提示显示,但没有任何文本。以下代码用于生成工具提示:
1.Code 创建 .toolTip 的位置
.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.Code 创建变量的位置。
var tooltip = d3.select("body")
.append("div")
.attr("class", "toolTip");
尝试附加到节点的代码
// 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");});
这是因为您没有任何与工具提示关联的数据。您的代码需要是这样的:
var t = d3.select("body")
.selectAll("div")
.data(<your data>)
.enter()
.append("div")
.attr("class", "toolTip");
现在您的 div 已附加数据以进行迭代。
让我们看一下mousemove调用的函数:
.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
指的是绑定在svg圆上的基准工具提示。在这种情况下,两个 d
指的不是同一件事。您没有任何数据绑定到工具提示,所以这将不起作用 - d
这里未定义,因此您的错误消息:"Cannot read property 'Name' of undefined."
相反,只需使用圆的基准:
.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
方法中看到 function(d) 时,您正在访问当前选择的每个元素的数据。你不想要与工具提示关联的数据,所以你不需要在 .html()
方法中使用 function(d)
,你已经在第一行访问了你想要的数据。
您似乎在使用 d3 分层布局。如果您以这样的形式开始,这将改变您的数据结构:
var data = { "name": "Parent", "children": [
{ "name": "Child A", "children": [ { "name": "Grandchild" } ] },
{ "name": "Child B", }
] };
d3.hierarchy(data)
将 return 具有以下结构的数组:
[
{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() 创建的数据结构。