不显示 D3 树工具提示



我一直在尝试向 d3 树的节点添加工具提示。 我已经看过这个例子,我的这段代码基于这个例子:

nodeEnter.append('rect')
...
.on('mouseover', function (d) {
var foHeight = rect_height;
var foWidth = rect_width;
var t = 50, k = 15;
var tip = {'w': (3/4 * t), 'h': k};
var anchor = {'w': 100/3, 'h': 100/3};
var fo = svg.append('foreignObject')
.attr('x', 0)
.attr('y', 0)
.attr('width', rect_width)
.attr('height', rect_height)
.attr('class', 'svg-tooltip');
var div = fo.append('xhtml:div')
.append('div')
.attr('class', 'tooltip');
console.log('div is :');
console.log(div);
div.append('p').html(function() {
console.log('dev append d is');
console.log(d);
if(d.data.tooltip || d.data.name) {
console.log('we have tooltip or name.');
console.log('name is' + d.data.name);
return '<div style="z-index:2 ; width: '
+ (125) + 'px; height: '
+ (42) + 'px;" class="node-text wordwrap" title="' + (d.data.tooltip || d.data.name) + '">'
+ '</div>';
}
});
fo.attr('height', 200);
svg.insert('polygon', '.svg-tooltip')
.attr({
'points': "0,0 0," + foHeight + " " + foWidth + "," + foHeight + " " + foWidth + ",0 " + (t) + ",0 " + tip.w + "," + (-tip.h) + " " + (t/2) + ",0",
'height': foHeight + tip.h,
'width': foWidth,
'fill': '#D8D8D8',
'opacity': 0.75,
'transform': 'translate(' + (anchor.w - tip.w) + ',' + (anchor.h + tip.h) + ')'
})
})    
.on('mouseout', function(d) {
console.log('mouse out of ' + d.data.name);
svg.selectAll('.svg-tooltip').remove();
svg.selectAll('polygon').remove();
});

当我将鼠标放在其中一个节点上时,我在开发人员的控制台中看到此输出......

div is :
Selection {_groups: Array(1), _parents: Array(1)}
dev append d is
Node {data: {…}, height: 0, depth: 2, parent: Node, x: 150, …}
have tooltip or name.
name isquoting-es-stg1-001

。但不显示工具提示。 我做错了什么?

谢谢!

这里的代码存在一些问题。该示例不是最容易改编的,因为:

  • 工具提示的位置是硬编码的 (anchor = {'w': width/3, 'h': height/3})
  • 该代码段将 d3v3 .attr() 与对象一起使用(如前所述)
  • 目前还不清楚一些变量代表什么。

首先,我们想知道工具提示应该放在哪里,我选择了:

.on('mouseover', function (d) {
// Get highlight rectangle:
var rect = d3.select(this); // the selected rect.
// Get bottom middle of rectangle:
var x = +rect.attr("x") + rectWidth/2;
var y = +rect.attr("y") + rectHeight;
...

这将获取鼠标悬停矩形底部边缘的中间。

我们需要将其应用于外来对象(包含文本)和多边形(包含阴影 + 形状 - 可以在没有 svg 多边形的纯 css 中完成):

// for the foreign object:
var fo = svg.append('foreignObject')
.attr('x', x)
.attr('y', y)
// And for the polygon:
.attr("transform","translate("+[x-tip.w,y+tip.h/2]+")");

如果我们用一个单独的 .attr("property",value) 行或使用 d3.selection-multi 和 .attrs() 替换出现的地方 .attr(),那么我们应该有一些工作。

最后,foWidth 和 foHeight 可能与 rectWidth 和 rectHeight 不同,否则任何大于矩形的工具提示都会被截断文本。虽然,您确实将异物的宽度覆盖为 200,因此它不是 rectWidth

我相信这些是我在下面所做的所有更改:

var rectWidth = 28;
var rectHeight = 28;

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

var data = d3.range(16);
var color = d3.interpolateBlues;

var nodeEnter = svg.selectAll(null)
.data(data)
.enter()
.append("rect")
.attr("x", function(d,i) {
return i%4 * (rectWidth+2);
})
.attr("y", function(d,i) {
return Math.floor(i/4) * (rectHeight+2);
})
.attr("width",rectWidth)
.attr("height",rectHeight)
.attr("fill", function(d,i) {
return color((Math.floor(i/4)+1) * (i%4+1) /16)
})
.on('mouseover', function (d) {
// Get highlight rectangle:
var rect = d3.select(this); // the selected rect.
// Get bottom middle of rectangle:
var x = +rect.attr("x") + rectWidth/2;
var y = +rect.attr("y") + rectHeight;

// Dimensions of foreign object:
var foHeight = 50;
var foWidth = 200;

// tooltip triangle info:
var t = 50, k = 15;
var tip = {'w': (3/4 * t), 'h': k};
//Foreign  object:
var fo = svg.append('foreignObject')
.attr('x', x)
.attr('y', y)
.attr('width', foWidth)
.attr('height', foHeight)
.attr('class', 'svg-tooltip')

// FO's Div:
var div = fo.append('xhtml:div')
.append('div')
.attr("class","tooltip");
// Div's p:
div.append('p').html(function() {
return "This is square: " + d; 
})

// SVG polygon that creates the background for the FO:
svg.insert('polygon', '.svg-tooltip')
.attr('points', "0,0 0," + foHeight + " " + foWidth + "," + foHeight + " " + foWidth + ",0 " + (t) + ",0 " + tip.w + "," + (-tip.h) + " " + (t/2) + ",0")
.attr('height', foHeight)
.attr('width',foWidth)
.attr('fill','#D8D8D8')
.attr('opacity',0.75)
.attr('transform',"translate("+[x-tip.w,y+tip.h/2]+")")
}).on('mouseout', function() {
svg.selectAll('.svg-tooltip').remove();
svg.selectAll('polygon').remove();       
})
svg {
display: block;
margin: 0 auto;
}
.svg-tooltip {
pointer-events: none;
}
.tooltip {
padding: 10px;
color: #4A22FF;
}
.lead {
font-style: italic;
}
p {
margin: 5px 0px;
}
polygon {
pointer-events: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

但是,基于异物/svg 的工具提示有局限性。除非工具提示在接近 SVG 底部时从底部锚定,否则可能会被切断。将div(不是包含div 的异物)放置在鼠标所在的 SVG 上的工具提示将在这方面有所帮助。D3noob 就是一个很好的例子。

最新更新