Как добавить всплывающую подсказку к графике SVG?


92

У меня есть серия прямоугольников svg (с использованием D3.js), и я хочу отображать сообщение при наведении указателя мыши, сообщение должно быть окружено полем, которое действует как фон. Они оба должны быть идеально выровнены относительно друг друга и прямоугольника (сверху и по центру). Как лучше всего это сделать?

Я попытался добавить текст svg, используя атрибуты «x», «y», «width» и «height», а затем добавить прямоугольник svg. Проблема в том, что ориентир для текста находится посередине (поскольку я хочу, чтобы он был выровнен по центру, который я использовал text-anchor: middle), но для прямоугольника это верхняя левая координата, плюс я хотел немного поля вокруг текста, что делает его своего рода боль.

Другой вариант - использовать html div, что было бы неплохо, потому что я могу добавить текст и отступы напрямую, но я не знаю, как получить абсолютные координаты для каждого прямоугольника. Есть ли способ сделать это?


Если нет другого выхода, полагаю
начокаб

Это проблема, если использовать разметку для того, для чего она была разработана?
Phrogz

Просто это выглядит не так красиво, но я ценю ваш ответ
nachocab

Ответы:


15

Вы можете использовать титровальный элемент, как указано в Phrogz. Есть также несколько хороших всплывающих подсказок, таких как jQuery Tipsy http://onehackoranother.com/projects/jquery/tipsy/ (которые можно использовать для замены всех элементов заголовка), nvd3 Боба Монтеверде или даже всплывающая подсказка Twitter из их Bootstrap http: // twitter.github.com/bootstrap/


175

Можете ли вы использовать просто элемент SVG<title> и браузер по умолчанию, отображающий его? (Примечание: это не то же самое, что titleатрибут, который вы можете использовать в div / img / spans в 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>

В качестве альтернативы, если вы действительно хотите отображать HTML в своем SVG, вы можете встроить 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 для включения и выключения дисплея. Как показано выше, один из способов сделать так, чтобы метка отображалась в нужном месте, - это обернуть прямоугольник и HTML так, <g>чтобы они располагались вместе.

Чтобы использовать JS для определения местоположения элемента SVG на экране, вы можете использовать getBoundingClientRect(), например, http://phrogz.net/svg/html_location_in_svg_in_html.xhtml


У меня отлично работает вставка заголовка в элемент svg!
Шивам Аггарвал

2
Хороший ответ. Но учтите, что foreignObject это не поддерживается в Internet Explorer
Рехбан Хатри,

В Firefox SVG имеет размер 0x0? Похоже, вам нужно указать ширину и высоту, например<rect width="200" height="50"></rect>
Франклин Ю

2
К сожалению <title>, не влияет на мобильные устройства.
jengeb

Когда я пытаюсь добавить заголовок с помощью js и добавляю заголовок в качестве дочернего элемента.
Подсказка

36

Единственный хороший способ, который я нашел, - использовать Javascript для перемещения всплывающей подсказки <div>. Очевидно, это работает только в том случае, если у вас есть SVG внутри HTML-документа, а не отдельно. И для этого требуется 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>


3

Я всегда использую общий заголовок 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);

И скриншот хрома ...

введите описание изображения здесь


0

Я придумал что-то, используя только HTML + CSS. Надеюсь, это сработает для тебя

.mzhrttltp {
  position: relative;
  display: inline-block;
}
.mzhrttltp .hrttltptxt {
  visibility: hidden;
  width: 120px;
  background-color: #040505;
  font-size:13px;color:#fff;font-family:IranYekanWeb;
  text-align: center;
  border-radius: 3px;
  padding: 4px 0;
  position: absolute;
  z-index: 1;
  top: 105%;
  left: 50%;
  margin-left: -60px;
}

.mzhrttltp .hrttltptxt::after {
  content: "";
  position: absolute;
  bottom: 100%;
  left: 50%;
  margin-left: -5px;
  border-width: 5px;
  border-style: solid;
  border-color: transparent transparent #040505 transparent;
}

.mzhrttltp:hover .hrttltptxt {
  visibility: visible;
}
<div class="mzhrttltp"><svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 24 24" fill="none" stroke="#e2062c" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="feather feather-heart"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"></path></svg><div class="hrttltptxt">علاقه&zwnj;مندی&zwnj;ها</div></div>


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.