首页 > 解决方案 > 获取所有重叠特征的工具提示 D3

问题描述

我试图弄清楚我们如何为其他一些功能后面的功能添加工具提示。d3 中的重叠特征

例如,在图片中有一些圆圈相互重叠,如果鼠标悬停在重叠区域上,我想获取有关这两个特征/圆圈的信息。

代码和工具提示示例附在下面。

var svg = d3.select("svg"),
    width = +svg.attr("width"),
    height = +svg.attr("height"),
    radius = 32;

var circles = d3.range(20).map(function() {
  return {
    x: Math.round(Math.random() * (width - radius * 2) + radius),
    y: Math.round(Math.random() * (height - radius * 2) + radius)
  };
});

var color = d3.scaleOrdinal()
    .range(d3.schemeCategory20);

var tooltip = d3.select("body")
    .append("div")
    .style("position", "absolute")
    .style("z-index", "10")
    .style("visibility", "hidden")
    .text("a simple tooltip");

  
svg.selectAll("circle")
  .data(circles)
  .enter().append("circle")
    .attr("cx", function(d) { return d.x; })
    .attr("cy", function(d) { return d.y; })
    .attr("r", radius)
    .on("mouseover", function(d){
  return tooltip.style("visibility", "visible");
})
    .on("mousemove", function(d){
  return tooltip
    .html("Radius: " + d.x)
    .style("top", (event.pageY-10)+"px").style("left",      (event.pageX+10)+"px");
})
    .on("mouseout", function(d){return tooltip.style("visibility", "hidden");})
    
  .style("fill", function(d, i) { return color(i); })
    .call(d3.drag()
        .on("start", dragstarted)
        .on("drag", dragged)
        .on("end", dragended));

function dragstarted(d) {
  d3.select(this).raise().classed("active", true);
}

function dragged(d) {
  d3.select(this).attr("cx", d.x = d3.event.x).attr("cy", d.y = d3.event.y);
}

function dragended(d) {
  d3.select(this).classed("active", false);
}
svg {
  border: 1px solid black;
}

.active {
  stroke: #000;
  stroke-width: 2px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.2/d3.min.js"></script>
<svg width="960" height="500"></svg>

标签: javascriptd3.jsmouseover

解决方案


这将计算鼠标位置与所有其他圆圈的距离,以测试鼠标是否超过一个圆圈:

<!DOCTYPE html>

<html>
  <body>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.2/d3.min.js"></script>
    <svg width="500" height="500"></svg>

    <script>
      var svg = d3.select('svg'),
        width = +svg.attr('width'),
        height = +svg.attr('height'),
        radius = 32;

      var circles = d3.range(20).map(function () {
        return {
          x: Math.round(Math.random() * (width - radius * 2) + radius),
          y: Math.round(Math.random() * (height - radius * 2) + radius),
        };
      });

      var color = d3.scaleOrdinal().range(d3.schemeCategory20);

      var tooltip = d3
        .select('body')
        .append('div')
        .style('position', 'absolute')
        .style('z-index', '10')
        .style('visibility', 'hidden')
        .text('a simple tooltip');

      var circles = svg
        .selectAll('circle')
        .data(circles)
        .enter()
        .append('circle')
        .attr('cx', function (d) {
          return d.x;
        })
        .attr('cy', function (d) {
          return d.y;
        })
        .attr('r', radius)
        .on('mouseover', function (d) {
          return tooltip.style('visibility', 'visible');
        })
        .on('mousemove', function (d) {

          var txt = 'X: ' + d.x,
              m = d3.mouse(this);

          circles.each(function(d1){
            // if not circle with "mouseover"
            if (d.x !== d1.x || d.y !== d1.y)
            {
              // check distance
              if (Math.sqrt((d1.x - m[0])**2 + (d1.y - m[1])**2) <= 32)
              {
                // add to tooltip
                txt += '<br/> X: ' + d1.x;
              }
            }
          });
          return tooltip
            .html(txt)
            .style('top', event.pageY - 10 + 'px')
            .style('left', event.pageX + 10 + 'px');
        })
        .on('mouseout', function (d) {
          return tooltip.style('visibility', 'hidden');
        })

        .style('fill', function (d, i) {
          return color(i);
        })
        .call(
          d3
            .drag()
            .on('start', dragstarted)
            .on('drag', dragged)
            .on('end', dragended)
        );

      function dragstarted(d) {
        d3.select(this).raise().classed('active', true);
      }

      function dragged(d) {
        d3.select(this)
          .attr('cx', (d.x = d3.event.x))
          .attr('cy', (d.y = d3.event.y));
      }

      function dragended(d) {
        d3.select(this).classed('active', false);
      }
    </script>
  </body>
</html>


推荐阅读