SVG D3.js将元素附加到SVG g:circle on text mouseover

时间:2014-07-22 13:55:36

标签: svg d3.js

抓住我的头。

我们在页面左侧有一个文本列表。列表中的每个项目都有一个data-id属性,可以很容易地在SVG地图中匹配相应的学校。此SVG地图是美国的地图,其学校位置从CSV excel表格输入并存储在“学校”中以供访问。

                circles.selectAll("circles")
            .data(schools)
            .enter().append("svg:a")
            .attr("xlink:href", function(d) { return d.url; })
            .append("svg:circle")
            .attr("school", function(d, i) { return d.name; })
            .attr("id", function(d, i) { return d.id; })
            .attr("cx", function(d,i) { return d.longitude; })
            .attr("cy", function(d,i) { return d.latitude; })
            .attr("r", function(d,i) { return 6; })
            .attr("i", function(d,i) { return i; })
            .attr("class", "icon")

因此,当用户将鼠标悬停在我之前提到的此文本列表上时,我会使用此功能:

                mapSearch = function(id) {
                  d3.selectAll("circle")
                    .filter(function(d) {
                      if (d.id == id) {
                          return show_bubble_2(d);
                       }
                    })
               }

哪个电话:

show_bubble_2 = function(school_data) {
                var school_info = school_data,
                    latitude = school_info.latitude,
                    longitude = school_info.longitude;


                        bubble.css({
                            "left": (longitude - 75)+"px",
                            "top": (latitude - 67)+"px"
                        });

                bubble.html("<h1>" + school_info.name + "</h1>" + "<p>" + school_info.city + ", " + school_info.state + "</p>")
                                        .attr("class", function(d) { return school_info.letter; });
                bubble.addClass("active");
            }

除非我们开始调整地图大小以适应不同的屏幕尺寸,或者除非我们在地图上执行特殊缩放功能,否则此方法无效。然后靠近西海岸的气泡就是他们应该去的地方,但是东海岸的气泡却离开了。简而言之,这是一场彻底的噩梦,而且根本不可扩展。

我的问题:如何将此DIV附加到相应的圆ID而不是使用绝对定位的DIV,这样无论地图的大小如何,气泡都会始终弹出该圆圈的顶部

我已经尝试在if(d.id == id){}中添加内容,但它总是返回错误,到目前为止我还没弄明白。我会继续沿着这些方向尝试一些东西,因为我觉得这样做是可行的。如果你有更好的解决方案或者能指出我正确的方向,我会非常感激。

谢谢,并且有一个好的!

2 个答案:

答案 0 :(得分:1)

即使使用Element.getBoundingClientRect应用了变换,您也可以找到圆的位置。

您可以使用已筛选的选择,获取.node()并找到其边界矩形。然后,通过调整滚动位置,您可以找到topleft的值,以便为您的气泡提供。

这意味着气泡的位置取决于圆圈在页面上显示的实际位置,而不是基于其数据,这需要您考虑转换。尝试这样的事情:

mapSearch = function(id) {

  // get the selection for the single element that matches id
  var c = d3.selectAll("circle")
    .filter(function(d) {
      if (d.id == id) {
        return show_bubble_2(d);
      }
    });

  // get the bounding rect for that selection's node (the actual circle element)
  var bcr = c.node().getBoundingClientRect();

  // calculate the top/left based on bcr and scroll position
  var bubbleTop = bcr.top + document.body.scrollTop + 'px',
      bubbleLeft = bcr.left + document.body.scrollLeft + 'px';

  // set the top and left positions
  bubble.css({
    'top': bubbleTop,
    'left': bubbleLeft
  });

}

当然,如果您正在缩放或平移并希望气泡保留在圆上,则需要在缩放和平移功能中重新计算这些值,但过程将是相同的。

HERE是一个使用圈子的演示,这些圈子随机放置在应用了平移和缩放的g元素中。单击列表中的项目以将气泡放置在相应的圆上。

答案 1 :(得分:0)

<div>是HTML。 <circle>是SVG。你不能(轻松地)将HTML元素放在SVG中。您必须使用<foreignobject>元素才能执行此操作。 (有关详细信息,请参阅this question。)或者,您可以使用原始SVG元素,例如<tspan>而不是<div>