d3树工具提示未出现

时间:2019-04-05 21:30:27

标签: javascript d3.js

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

    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

...,但没有工具提示出现。我在做什么错了?

谢谢!

1 个答案:

答案 0 :(得分:2)

此处的代码存在一些问题。该示例最不容易适应,因为:

  • 工具提示的位置是硬编码(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()出现的位置替换为具有单个.attr(“ property”,value)行或使用d3.selection-multi和.attrs()的对象,那么我们应该可以使用。

最后,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对此有很好的example