如何向 svg 图形添加工具提示?

IT技术 javascript svg d3.js tooltip
2021-02-07 19:47:20

我有一系列 svg 矩形(使用 D3.js),我想在鼠标悬停时显示一条消息,该消息应该被一个作为背景的框包围。它们应该彼此完美对齐并与矩形(在顶部和中心)对齐。做这个的最好方式是什么?

我尝试使用“x”、“y”、“宽度”和“高度”属性添加一个 svg 文本,然后添加一个 svg 矩形。问题是文本的参考点在中间(因为我希望它居中对齐我使用过text-anchor: middle),但对于矩形,它是左上角的坐标,另外我想要在文本周围留一点边距,这使它有点像一种痛苦。

另一个选项是使用 html div,这很好,因为我可以直接添加文本和填充,但我不知道如何获取每个矩形的绝对坐标。有没有办法做到这一点?

6个回答

你能简单地使用SVG<title>元素和它传达的默认浏览器渲染吗?(注:这是一样的title,你可以上使用属性DIV / IMG /跨度在HTML,它需要一个子元素命名title

rect {
  width: 100%;
  height: 100%;
  fill: #69c;
  stroke: #069;
  stroke-width: 5px;
  opacity: 0.5
}
<p>Mouseover the rect to see the tooltip on supporting browsers.</p>

<svg xmlns="http://www.w3.org/2000/svg">
  <rect>
    <title>Hello, World!</title>
  </rect>
</svg>

或者,如果你真的想在你的 SVG 中显示 HTML,你可以直接嵌入 HTML:

rect {
  width: 100%;
  height: 100%;
  fill: #69c;
  stroke: #069;
  stroke-width: 5px;
  opacity: 0.5
}

foreignObject {
  width: 100%;
}

svg div {
  text-align: center;
  line-height: 150px;
}
<svg xmlns="http://www.w3.org/2000/svg">
  <rect/>
  <foreignObject>
    <body xmlns="http://www.w3.org/1999/xhtml">
      <div>
        Hello, <b>World</b>!
      </div>
    </body>      
  </foreignObject>
</svg>

…但是你需要 JS 来打开和关闭显示。如上所示,使标签出现在正确位置的一种方法是将 rect 和 HTML 包裹在同一<g>位置,将它们放在一起。

要使用 JS 查找 SVG 元素在屏幕上的位置,您可以使用getBoundingClientRect(),例如http://phrogz.net/svg/html_location_in_svg_in_html.xhtml

非常适合我将标题插入 svg 元素!
2021-03-22 19:47:20
很好的答案。但请注意foreignObject Internet Explorer 不支持
2021-03-22 19:47:20
我在 Chrome 80 中没有看到您的第二个示例的任何工具提示
2021-03-26 19:47:20
不幸的是<title>对移动设备没有影响。
2021-03-29 19:47:20
在 Firefox 上,SVG 的大小为 0x0?似乎您必须指定宽度和高度,例如<rect width="200" height="50"></rect>
2021-03-30 19:47:20

我发现的唯一好方法是使用 Javascript 来移动工具提示<div>显然,这仅在 HTML 文档中有 SVG 时才有效 - 而不是独立的。它需要Javascript。

function showTooltip(evt, text) {
  let tooltip = document.getElementById("tooltip");
  tooltip.innerHTML = text;
  tooltip.style.display = "block";
  tooltip.style.left = evt.pageX + 10 + 'px';
  tooltip.style.top = evt.pageY + 10 + 'px';
}

function hideTooltip() {
  var tooltip = document.getElementById("tooltip");
  tooltip.style.display = "none";
}
#tooltip {
  background: cornsilk;
  border: 1px solid black;
  border-radius: 5px;
  padding: 5px;
}
<div id="tooltip" display="none" style="position: absolute; display: none;"></div>

<svg>
  <rect width="100" height="50" style="fill: blue;" onmousemove="showTooltip(evt, 'This is blue');" onmouseout="hideTooltip();" >
  </rect>
</svg>

您可以使用 Phrogz 指示的标题元素。还有一些很好的工具提示,如 jQuery 的 Tipsy http://onehackoranother.com/projects/jquery/tipsy/(可用于替换所有标题元素)、Bob Monteverde 的 nvd3 甚至 Twitter 的 Bootstrap 工具提示http:// twitter.github.com/bootstrap/

在 svg 上,写标题的正确方法

<svg>
  <title id="unique-id">Checkout</title>
</svg>

在此处查看更多详细信息https://css-tricks.com/svg-title-vs-html-title-attribute/

我总是在我的设置中使用通用的 css 标题。我只是在为我的博客管理页面构建分析。我不需要任何花哨的东西。这是一些代码...

let comps = g.selectAll('.myClass')
   .data(data)
   .enter()
   .append('rect')
   ...styling...
   ...transitions...
   ...whatever...

g.selectAll('.myClass')
   .append('svg:title')
   .text((d, i) => d.name + '-' + i);

以及 chrome 的屏幕截图...

在此处输入图片说明