Come aggiungere un suggerimento a un grafico svg?


92

Ho una serie di rettangoli svg (usando D3.js) e voglio visualizzare un messaggio al passaggio del mouse, il messaggio dovrebbe essere circondato da una casella che funge da sfondo. Dovrebbero essere entrambi perfettamente allineati tra loro e con il rettangolo (in alto e al centro). Qual è il modo migliore per farlo?

Ho provato ad aggiungere un testo in formato svg utilizzando gli attributi "x", "y", "larghezza" e "altezza", quindi anteponendo un rect in formato svg. Il problema è che il punto di riferimento per il testo è nel mezzo (poiché lo voglio allineato al centro l'ho usato text-anchor: middle), ma per il rettangolo è la coordinata in alto a sinistra, in più volevo un po 'di margine attorno al testo che lo rende un po' un dolore.

L'altra opzione era usare un div html, il che sarebbe carino, perché posso aggiungere il testo e il riempimento direttamente ma non so come ottenere le coordinate assolute per ogni rettangolo. C'è un modo per fare questo?


Se non c'è altro modo, immagino
nachocab

È un problema usare il markup per ciò per cui è stato progettato?
Phrogz

È solo che non sembra così carino, ma apprezzo la tua risposta
nachocab

Risposte:



175

Puoi usare semplicemente l' elemento SVG<title> e il rendering predefinito del browser che trasmette? (Nota: questo non è lo stesso titledell'attributo che puoi usare su div / img / spans in html, deve essere un elemento figlio denominato 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>

In alternativa, se vuoi davvero mostrare l'HTML nel tuo SVG, puoi incorporare l'HTML direttamente:

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>

... ma poi avresti bisogno di JS per accendere e spegnere il display. Come mostrato sopra, un modo per far apparire l'etichetta nel punto giusto è avvolgere il rect e l'HTML nello stesso <g>che li posiziona entrambi insieme.

Per usare JS per trovare dove si trova un elemento SVG sullo schermo, puoi usare getBoundingClientRect(), ad esempio, http://phrogz.net/svg/html_location_in_svg_in_html.xhtml


Funziona bene per me inserire il titolo in un elemento svg!
Shivam Aggarwal

2
Bella risposta. Ma tieni presente che foreignObject non è supportato in Internet Explorer
Rehban Khatri

Su Firefox l'SVG ha dimensione 0x0? Sembra che tu debba specificare larghezza e altezza come<rect width="200" height="50"></rect>
Franklin Yu

2
Purtroppo <title>non ha alcun effetto sui dispositivi mobili.
jengeb

Quando provo ad aggiungere il titolo usando js e aggiungo il titolo come elemento figlio. Il suggerimento non viene visualizzato :(
Ankur Marwaha

36

L'unico buon modo che ho trovato è stato usare Javascript per spostare un tooltip <div>. Ovviamente questo funziona solo se hai SVG all'interno di un documento HTML, non standalone. E richiede 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

Vado sempre con il titolo CSS generico con il mio setup. Sto solo creando analisi per la mia pagina di amministrazione del blog. Non ho bisogno di niente di speciale. Ecco un po 'di codice ...

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

E uno screenshot di Chrome ...

inserisci qui la descrizione dell'immagine


0

Ho inventato qualcosa usando solo HTML + CSS. Spero che funzioni per te

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


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.