在 d3.js 地图中添加工具提示

Posted

技术标签:

【中文标题】在 d3.js 地图中添加工具提示【英文标题】:Adding tooltip in d3.js map 【发布时间】:2013-12-02 23:14:55 【问题描述】:

当您将鼠标悬停在 d3.js 中的地图上时,我正在尝试添加一个工具提示来显示地区名称。输入是一个 topojson 文件,我已经能够成功地生成带有区域边界的地图并突出显示当前选择的区域。

对于工具提示,我尝试执行类似于this 的操作,但什么也没有发生。我使用的代码如下所示。工具提示代码接近尾声。

var width = 960,
    height = 600;

var projection = d3.geo.albers()
    .center([87, 28])
    .rotate([-85, 0])
    .parallels([27, 32]);

var path = d3.geo.path()
    .projection(projection);

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

svg.append("rect")
    .attr("width", width)
    .attr("height", height);  

var g = svg.append("g");  

var div = d3.select("body").append("div")
  .attr("class", "tooltip")
  .style("opacity", 1e-6);

d3.json("data/nepal3.json", function(error, npl) 
    var districts = topojson.feature(npl, npl.objects.nepal_districts);

    projection
      .scale(1)
      .translate([0, 0]);

    var b = path.bounds(districts),
      s = .95 / Math.max((b[1][0] - b[0][0]) / width, (b[1][1] - b[0][1]) / height),
      t = [(width - s * (b[1][0] + b[0][0])) / 2, (height - s * (b[1][1] + b[0][1])) / 2];

    projection
      .scale(s)
      .translate(t);

      g.selectAll(".nepal_districts")
          .data(districts.features)
        .enter().append("path")
          .attr("class", function(d)  return "nepal_districts " + d.id; )
          .attr("d", path)
          .on("mouseover", function(d,i) 
              d3.select(this.parentNode.appendChild(this)).transition().duration(300)
                  .style('stroke-width':2,'stroke':'#333333','stroke-linejoin':'round','cursor':'pointer','fill':'#b9270b');
          )
          .on("mouseout", function(d,i) 
              d3.select(this.parentNode.appendChild(this)).transition().duration(100)
                  .style('stroke-width':2,'stroke':'#FFFFFF','stroke-linejoin':'round','fill':'#3d71b6');
          );

      g.append("path")
          .datum(topojson.mesh(npl, npl.objects.nepal_districts, function(a, b)  return a !== b;))
          .attr("d", path)
          .attr("class", "district-boundary");

      /* Tooltip */

      g.selectAll(".nepal_districts")
          .data(districts.features)
        .enter().append("text")
          .append("svg:rect")
            .attr("width", 140)
            .attr("height", 140)
            .text(function(d)  return d.properties.name; )
            .on("mouseover", mouseover)
            .on("mousemove", mousemove)
            .on("mouseout", mouseout);

      function mouseover() 
        div.transition()
            .duration(300)
            .style("opacity", 1);
      

      function mousemove() 
        div
            .text(d3.event.pageX + ", " + d3.event.pageY)
            .style("left", (d3.event.pageX - 34) + "px")
            .style("top", (d3.event.pageY - 12) + "px");
      

      function mouseout() 
        div.transition()
            .duration(100)
            .style("opacity", 1e-6);
       

);

CSS 是

div.tooltip    
  position: absolute;           
  text-align: center;           
  width: 60px;                  
  height: 28px;                 
  padding: 2px;             
  font: 12px sans-serif;        
  background: #4c4c4c;   
  border: 0px;      
  border-radius: 8px;           
  pointer-events: none;         

我为“工具提示”添加的代码根本没有任何作用。我在这里做错了什么?

topojson 文件具有这种格式。我想让“名称”属性显示在工具提示中。


  "type": "Topology",
  "objects": 
    "nepal_districts": 
      "type": "GeometryCollection",
      "geometries": [
        
          "type": "Polygon",
          "id": 0,
          "properties": 
            "name": "HUMLA"
          ,
          "arcs": [
            [
              0,
              1,
              2,
              3
            ]
          ]
        ,

【问题讨论】:

你见过this article吗? 您的工具提示可能隐藏在地图后面。工具提示显示时的位置在哪里?如果它没有显示,您可能需要使外部容器具有位置:相对。 bl.ocks.org/Caged/6476579 【参考方案1】:

有一个类似的问题,我最终将绝对定位的工具提示添加到 body 元素,并根据鼠标位置修改其位置。

添加到指令:

function addTooltip(accessor) 
    return function(selection) 
        var tooltipDiv;
        var bodyNode = d3.select('body').node();

        selection.on("mouseover", function(topoData, countryIndex) 
            if (!accessor(topoData, countryIndex)) 
                return;
            
            // Clean up lost tooltips
            d3.select('body').selectAll('div.tooltipmap').remove();
            formatValue(topoData, countryIndex);

            tooltipDiv = d3.select('body').append('div').attr('class', 'tooltipmap');
            var absoluteMousePos = d3.mouse(bodyNode);
            tooltipDiv.style('left', (absoluteMousePos[0] + 10) + 'px')
                .style('top', (absoluteMousePos[1] - 15) + 'px')
                .style('opacity', 1)
                .style('z-index', 1070);
            accessor(topoData, countryIndex) || '';
        )

            .on('mousemove', function(topoData, countryIndex) 
                if (!accessor(topoData, countryIndex)) 
                    return;
                
                var absoluteMousePos = d3.mouse(bodyNode);
                tooltipDiv.style('left', (absoluteMousePos[0] + 10) + 'px')
                    .style('top', (absoluteMousePos[1] - 15) + 'px');
                var tooltipText = accessor(topoData, countryIndex) || '';
                tooltipDiv.html(tooltipText);
            )

            .on("mouseout", function(topoData, countryIndex) 
                if (!accessor(topoData, countryIndex)) 
                    return;
                
                tooltipDiv.remove();
            );
    ;


.tooltipmap 
  background-color: #000000;
  margin: 10px;
  height: 50px;
  width: 150px;
  padding-left: 10px; 
  padding-top: 10px;
  border-radius: 5px;
  overflow: hidden;
  display: block;
  color: #FFFFFF;
  font-size: 12px;
  position: absolute;
  opacity: 1;
  h6
    margin: 0;
    padding: 0;
  
  p
    color: #FFFFFF;
  

希望对你有帮助!

【讨论】:

以上是关于在 d3.js 地图中添加工具提示的主要内容,如果未能解决你的问题,请参考以下文章

如何在 d3.js 中同步地图和点图层的比例和位置?

D3.js系列——交互式操作和布局

可缩放旭日形图 (D3.js) 中损坏的图例和工具提示

D3.js:使用元素位置而不是鼠标位置定位工具提示?

如何使用 MapKit (SwiftUI) 将工具提示添加到地图注释以在地图上显示位置名称

使用 D3 JS 将鱼眼添加到轴