关于javascript:D3.js:使用元素位置而非鼠标位置来定位工具提示?

D3.js: Position tooltips using element position, not mouse position?

我正在使用D3绘制散点图。当用户将鼠标悬停在每个圆圈上时,我想显示工具提示。

我的问题是我可以追加工具提示,但是它们是使用鼠标事件d3.event.pageXd3.event.pageY进行定位的,因此它们在每个圆上的位置不一致。

相反,有些在圆的左边,有些在右边-这取决于用户的鼠标进入圆的方式。

这是我的代码:

1
2
3
4
5
6
7
8
9
circles
  .on("mouseover", function(d) {        
    tooltip.html(d)  
      .style("left", (d3.event.pageX) +"px")    
      .style("top", (d3.event.pageY - 28) +"px");    
  })                  
  .on("mouseout", function(d) {      
    tooltip.transition().duration(500).style("opacity", 0);  
  });

并且是显示问题的JSFiddle:http://jsfiddle.net/WLYUY/5/

是否可以使用圆心本身作为工具提示(而不是鼠标位置)的方向?


在特定情况下,您只需使用d定位工具提示,即

1
2
3
tooltip.html(d)  
  .style("left", d +"px")    
  .style("top", d +"px");

为使这一点更为通用,您可以选择鼠标悬停在其上的元素并获取其坐标以定位工具提示,即

1
2
3
tooltip.html(d)  
  .style("left", d3.select(this).attr("cx") +"px")    
  .style("top", d3.select(this).attr("cy") +"px");


在此处找到了一些内容,即使<body><svg>的位置不同,也可以解决您的问题。假设您为工具提示设置了absolute位置。

1
2
3
4
5
6
7
.on("mouseover", function(d) {
    var matrix = this.getScreenCTM()
        .translate(+ this.getAttribute("cx"), + this.getAttribute("cy"));
    tooltip.html(d)
        .style("left", (window.pageXOffset + matrix.e + 15) +"px")
        .style("top", (window.pageYOffset + matrix.f - 30) +"px");
})


以我的经验,简易解决方案如下:

首先,getBoundingClientRect()获取元素的位置。

然后,使用window.pageYOffset调整相对于您所在位置的高度。

例如

1
2
3
4
5
6
.on('mouseover', function(d) {
    let pos = d3.select(this).node().getBoundingClientRect();
    d3.select('#tooltip')
        .style('left', `${pos['x']}px`)
        .style('top', `${(window.pageYOffset  + pos['y'] - 100)}px`);
})

在上面的示例中,我不使用X \\的偏移量,因为我们几乎不需要(除非您水平滚动)。

添加window.pageYOffsetpos['y']将为我们提供当前的鼠标位置(无论我们在页面上的什么位置)。我减去100,将工具提示放在其上方一点。


我是D3的新手,所以它可能不适用于散点图...但是发现它似乎适用于条形图...其中v1和v2是要绘制的值..数据数组中的值。

1
2
3
4
5
6
7
.on("mouseover", function(d) {
                  divt .transition()
                      .duration(200)
                      .style("opacity", .9);
                  divt .html(d.v1)
                      .style("left", x(d.v2)+50 +"px")
                      .style("top",y(d.v1)+"px");})