Как добавить всплывающую подсказку к графике 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.