Jak dodać podpowiedź do grafiki SVG?


92

Mam serię prostokątów svg (używając D3.js) i chcę wyświetlić komunikat po najechaniu myszą, wiadomość powinna być otoczona ramką, która działa jako tło. Powinny być idealnie wyrównane względem siebie i prostokąta (na górze i na środku). Jaki jest najlepszy sposób, aby to zrobić?

Próbowałem dodać tekst svg, używając atrybutów „x”, „y”, „szerokość” i „wysokość”, a następnie wstawiłem na początku prostokąt svg. Problem polega na tym, że punkt odniesienia dla tekstu znajduje się pośrodku (ponieważ chcę, aby był wyśrodkowany, użyłem text-anchor: middle), ale dla prostokąta jest to współrzędna górna lewa, plus chciałem trochę marginesu wokół tekstu, co sprawia, że ​​jest trochę ból.

Inną opcją było użycie elementu div html, co byłoby fajne, ponieważ mogę bezpośrednio dodać tekst i wypełnienie, ale nie wiem, jak uzyskać bezwzględne współrzędne dla każdego prostokąta. Czy jest na to sposób?


Jeśli nie ma innego wyjścia, jak sądzę
— nachocab

Czy to problem, używając znaczników do tego, do czego został zaprojektowany?
— Phrogz

Po prostu nie wygląda to tak ładnie, ale doceniam twoją odpowiedź
— nachocab

Odpowiedzi:



175

Czy możesz użyć po prostu elementu SVG<title> i domyślnej przeglądarki, którą on przekazuje? (Uwaga: to nie to samo, co titleatrybut, którego możesz użyć w div / img / spans w html, musi to być element podrzędny o nazwie 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>

Alternatywnie, jeśli naprawdę chcesz wyświetlić HTML w swoim SVG, możesz bezpośrednio osadzić 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>

… Ale wtedy do włączania i wyłączania wyświetlacza potrzebny byłby JS. Jak pokazano powyżej, jednym ze sposobów umieszczenia etykiety we właściwym miejscu jest umieszczenie prostego i HTML w tym samym <g>miejscu, które ustawia je razem.

Aby użyć JS do znalezienia, gdzie na ekranie znajduje się element SVG, możesz użyć getBoundingClientRect()np. Http://phrogz.net/svg/html_location_in_svg_in_html.xhtml


Dobrze mi pasuje wstawianie tytułu do elementu svg!
— Shivam Aggarwal

2
Niezła odpowiedź. Należy jednak pamiętać, że foreignObject nie jest to obsługiwane w przeglądarce Internet Explorer
— Rehban Khatri

W przeglądarce Firefox plik SVG ma rozmiar 0x0? Wygląda na to, że musisz określić szerokość i wysokość, na przykład<rect width="200" height="50"></rect>
— Franklin Yu

2
Niestety <title>nie ma to wpływu na urządzenia mobilne.
— jengeb

Kiedy próbuję dodać tytuł za pomocą js i dołączając tytuł jako element podrzędny. Opis się nie pojawia :(
— Ankur Marwaha,

36

Jedynym dobrym sposobem, jaki znalazłem, było użycie Javascript do przesuwania podpowiedzi <div>. Oczywiście działa to tylko wtedy, gdy w dokumencie HTML znajduje się SVG - a nie samodzielny. I wymaga 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

Zawsze używam ogólnego tytułu CSS w mojej konfiguracji. Po prostu tworzę statystyki dla mojej strony administratora bloga. Nie potrzebuję niczego wymyślnego. Oto kod ...

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);

I zrzut ekranu z chrome ...

wprowadź opis obrazu tutaj


0

Wymyśliłem coś, używając tylko HTML + CSS. Mam nadzieję, że to działa dla Ciebie

.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>


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.