Angular D3 TopoJSON:鼠标悬停工具提示坐标错误

发布于 2025-01-09 03:01:33 字数 2527 浏览 1 评论 0原文

我正在尝试在 Angular 构建的页面上使用 D3,为美国 TopoJSON 地图中的县实现鼠标悬停时的 div 工具提示。

我已经尝试了 D3 鼠标悬停事件中可用的 x/y 坐标的每种组合,以及在线建议的一些组合(D3.pointerElement.getBoundingClientRect 等)。 ),但无论我做什么,工具提示似乎都落在不正确的坐标处,与我的鼠标偏移,并且在 svg 上的每个位置不一定有相同的度数。

有没有正确的方法来做到这一点?代码示例如下。相关部分位于 this.counties.on("mouseover", ...) 内。

HTML

<div class="row g-0">
  <div class="container" id="mapContainer">
    <svg id="map"></svg>
    <div id="tooltip">TESTING</div>
  </div>
</div>

CSS

#mapContainer {
  position: relative;
}
#tooltip {
  position: absolute;
}

TypeScript

    this.svg = d3.select("#map")
      .attr("preserveAspectRatio", "xMidYMid meet")
      .attr("viewBox", "0 0 960 600")
      .attr("height", "100%")
      .attr("width", "100%")

    this.g = this.svg.append("g")
      .attr("id", "g")

    this.zoom = d3.zoom()
      .scaleExtent([1, 8])
      .translateExtent([[0, 0], [960, 600]])
      .on("zoom", (event, d) => {
        let {transform} = event
        this.g.attr("transform", transform)
        this.g.attr("stroke-width", 1 / transform.k)
      })

    this.counties = this.g.append("g")
      .attr("class", "county")
      .attr("fill", "#DFDFDF")
      .attr("stroke", "#FFFFFF")
      .attr("stroke-linejoin", "round")
      .attr("stroke-width", "0.25")
      .selectAll('path')
      .data(topojson.feature(this.topography, this.topography["objects"]["counties"])["features"])
      .join("path")
      .attr("id", function(d) {return d["id"]})
      .attr('d', this.path)
      .attr("fill", "#DFDFDF")
      .on("mousemove", (event, d) => {

        d3.select("#tooltip")
          .style("left", `${d3.pointer(event)[0]}px`)
          .style("top", `${d3.pointer(event)[1]}px`)

      })

      // PER DERISTNOCHDA'S SUGGESTION
      .on("mousemove", (event, d) => {

        d3.select("#tooltip")
          .style("left", `${event.pageY}px`)
          .style("top", `${event.pageX}px`)

      })

一些结果屏幕截图,例如,当光标位于右上角的缅因州时:

在此处输入图像描述

当光标位于亚利桑那州时左下角:

在此处输入图像描述

I am trying to implement a div tooltip on mouseover for counties in a TopoJSON map of the United States, using D3 on a page built in Angular.

I have tried every combination of the x/y coordinates available in the D3 mouseover event, as well as some combinations suggested online (D3.pointer, Element.getBoundingClientRect, etc.), but no matter what I do the tooltip seems to fall at incorrect coordinates, offset from my mouse and not necessarily by the same degree at each location on the svg.

Is there a proper way to do this? Examples of code are below. The relevant portion is within this.counties.on("mouseover", ...).

HTML

<div class="row g-0">
  <div class="container" id="mapContainer">
    <svg id="map"></svg>
    <div id="tooltip">TESTING</div>
  </div>
</div>

CSS

#mapContainer {
  position: relative;
}
#tooltip {
  position: absolute;
}

TypeScript

    this.svg = d3.select("#map")
      .attr("preserveAspectRatio", "xMidYMid meet")
      .attr("viewBox", "0 0 960 600")
      .attr("height", "100%")
      .attr("width", "100%")

    this.g = this.svg.append("g")
      .attr("id", "g")

    this.zoom = d3.zoom()
      .scaleExtent([1, 8])
      .translateExtent([[0, 0], [960, 600]])
      .on("zoom", (event, d) => {
        let {transform} = event
        this.g.attr("transform", transform)
        this.g.attr("stroke-width", 1 / transform.k)
      })

    this.counties = this.g.append("g")
      .attr("class", "county")
      .attr("fill", "#DFDFDF")
      .attr("stroke", "#FFFFFF")
      .attr("stroke-linejoin", "round")
      .attr("stroke-width", "0.25")
      .selectAll('path')
      .data(topojson.feature(this.topography, this.topography["objects"]["counties"])["features"])
      .join("path")
      .attr("id", function(d) {return d["id"]})
      .attr('d', this.path)
      .attr("fill", "#DFDFDF")
      .on("mousemove", (event, d) => {

        d3.select("#tooltip")
          .style("left", `${d3.pointer(event)[0]}px`)
          .style("top", `${d3.pointer(event)[1]}px`)

      })

      // PER DERISTNOCHDA'S SUGGESTION
      .on("mousemove", (event, d) => {

        d3.select("#tooltip")
          .style("left", `${event.pageY}px`)
          .style("top", `${event.pageX}px`)

      })

A few screenshots of results, e.g., when the cursor is in Maine in the top-right:

enter image description here

And when the cursor is in Arizona in the bottom-left:

enter image description here

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

泪意 2025-01-16 03:01:33

使 div#tooltip 相对于页面(而不是其父页面)的位置为绝对位置。因此,您可以从CSS中删除它:

/* remove this */
#mapContainer {
  position: relative;
}

此外,您还应该使用event.pageX作为leftevent.pageY对于顶部

问题是您交换了 xy 值。

相关代码修改:

 .style("left", `${event.pageX}px`)
 .style("top", `${event.pageY}px`)

Make the div#tooltip's position absolute with respect to the page, not its parent. So you can remove this from your CSS:

/* remove this */
#mapContainer {
  position: relative;
}

Also you should use event.pageX for left and event.pageY for top.

The problem is that you've swapped x and y values.

Relevant code change:

 .style("left", `${event.pageX}px`)
 .style("top", `${event.pageY}px`)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文