Mostra i dati al passaggio del mouse del cerchio


162

Ho una serie di dati che sto tramando in una dispersione. Quando passo con il mouse su uno dei cerchi vorrei che si aprisse con i dati (come x, y valori, forse di più). Ecco cosa ho provato a usare:

vis.selectAll("circle")
   .data(datafiltered).enter().append("svg:circle")
   .attr("cx", function(d) { return x(d.x);})
   .attr("cy", function(d) {return y(d.y)})
   .attr("fill", "red").attr("r", 15)
   .on("mouseover", function() {
        d3.select(this).enter().append("text")
            .text(function(d) {return d.x;})
            .attr("x", function(d) {return x(d.x);})
            .attr("y", function (d) {return y(d.y);}); });

Sospetto di dover essere più informato su quali dati inserire?


1
Ho anche provato: vis.selectAll ("circle"). Each (function (d) {vis.append ("svg: text"). Attr ("x", dx) .attr ("y", dy) .text (funzione (d) {return dx;});}); inutilmente, ahimè.
ScottieB,

Risposte:


181

Presumo che quello che vuoi sia una descrizione comandi. Il modo più semplice per farlo è quello di aggiungere un svg:titleelemento a ciascun cerchio, poiché il browser si occuperà di mostrare la descrizione e non è necessario il gestore del mouse. Il codice sarebbe qualcosa di simile

vis.selectAll("circle")
   .data(datafiltered).enter().append("svg:circle")
   ...
   .append("svg:title")
   .text(function(d) { return d.x; });

Se si desidera utilizzare tooltip più elaborati, ad esempio è possibile utilizzare il brillo. Vedi qui per un esempio.


3
Mi piace alticcio. Il mio unico problema ora è che punta all'angolo in alto a sinistra del cerchio, piuttosto che al bordo come in quella demo. Non trovo alcuna ragione ovvia per cui. jsfiddle.net/scottieb/JwaaV (alticcio in fondo)
ScottieB

Che jsfiddle non sembra avere suggerimenti?
Lars Kotthoff,

Potresti provare ad aggiungere la descrizione comando a una svg:gsovrapposizione con il cerchio effettivo, ma dando larghezza e altezza zero. Attualmente sta prendendo il rettangolo di selezione e posizionando la descrizione comandi al limite. Anche giocare con le opzioni di Tipsy potrebbe essere d'aiuto.
Lars Kotthoff,

1
Non sembra più funzionare. Ho anche trovato un esempio usando svg: title che non riesce: bl.ocks.org/ilyabo/1339996
nn

1
@nos Funziona per me.
Lars Kotthoff,

145

Un ottimo modo per creare una descrizione comandi è descritto qui: Esempio di descrizione comandi D3 semplice

Devi aggiungere un div

var tooltip = d3.select("body")
    .append("div")
    .style("position", "absolute")
    .style("z-index", "10")
    .style("visibility", "hidden")
    .text("a simple tooltip");

Quindi puoi semplicemente attivarlo usando

.on("mouseover", function(){return tooltip.style("visibility", "visible");})
.on("mousemove", function(){return tooltip.style("top",
    (d3.event.pageY-10)+"px").style("left",(d3.event.pageX+10)+"px");})
.on("mouseout", function(){return tooltip.style("visibility", "hidden");});

d3.event.pageX/ d3.event.pageYè la coordinata corrente del mouse.

Se vuoi cambiare il testo puoi usare tooltip.text("my tooltip text");

Esempio di lavoro


4
Puoi associare i dati a questa descrizione comandi?
Jorge Leitao,

2
Inoltre, puoi associare i dati a ogni elemento DOM.
Pwdr,

per associare i dati a questo, basta aggiungere d all'interno della parentesi in questo modo: funzione (d) {... e cambiare il testo in qualsiasi cosa tu voglia. Ad esempio, supponiamo che tu abbia un nome: tooltip.text (d.name):
thatOneGuy

39

C'è una libreria fantastica per farlo che ho scoperto di recente. È semplice da usare e il risultato è abbastanza pulito: d3-tip.

Puoi vedere un esempio qui :

inserisci qui la descrizione dell'immagine

Fondamentalmente, tutto quello che devi fare è scaricare ( index.js ), includere lo script:

<script src="index.js"></script>

e quindi seguire le istruzioni da qui (stesso collegamento come esempio)

Ma per il tuo codice, sarebbe qualcosa del tipo:

definire il metodo:

var tip = d3.tip()
  .attr('class', 'd3-tip')
  .offset([-10, 0])
  .html(function(d) {
    return "<strong>Frequency:</strong> <span style='color:red'>" + d.frequency + "</span>";
  })

crea il tuo svg (come già fai)

var svg = ...

chiama il metodo:

svg.call(tip);

aggiungi un suggerimento al tuo oggetto:

vis.selectAll("circle")
   .data(datafiltered).enter().append("svg:circle")
...
   .on('mouseover', tip.show)
   .on('mouseout', tip.hide)

Non dimenticare di aggiungere il CSS:

<style>
.d3-tip {
  line-height: 1;
  font-weight: bold;
  padding: 12px;
  background: rgba(0, 0, 0, 0.8);
  color: #fff;
  border-radius: 2px;
}

/* Creates a small triangle extender for the tooltip */
.d3-tip:after {
  box-sizing: border-box;
  display: inline;
  font-size: 10px;
  width: 100%;
  line-height: 1;
  color: rgba(0, 0, 0, 0.8);
  content: "\25BC";
  position: absolute;
  text-align: center;
}

/* Style northward tooltips differently */
.d3-tip.n:after {
  margin: -1px 0 0 0;
  top: 100%;
  left: 0;
}
</style>

2
L'ultimo d3-tip supporta d3v4 bene. Non è ovvio se vai in giro con Google, ma funziona bene con me con d3v4.
moodboom

6

È possibile passare i dati da utilizzare nel passaggio del mouse in questo modo: l'evento del passaggio del mouse utilizza una funzione con i enterdati precedentemente modificati come argomento (e l'indice come secondo argomento), quindi non è necessario utilizzarli enter()una seconda volta.

vis.selectAll("circle")
.data(datafiltered).enter().append("svg:circle")
.attr("cx", function(d) { return x(d.x);})
.attr("cy", function(d) {return y(d.y)})
.attr("fill", "red").attr("r", 15)
.on("mouseover", function(d,i) {
    d3.select(this).append("text")
        .text( d.x)
        .attr("x", x(d.x))
        .attr("y", y(d.y)); 
});

Grazie. Avevo davvero bisogno d3.select(this)di modificare la forma e non sapevo come ottenere l'istanza in un invio / aggiornamento.
Turbo

Stai usando alcune funzioni x () e y () che non sono definite nel tuo codice. Penso che possa essere rimosso.
Robert,

furono dati nel PO
danimal

5

Questo esempio conciso dimostra un modo comune come creare una descrizione comandi personalizzata in d3.

var w = 500;
var h = 150;

var dataset = [5, 10, 15, 20, 25];

// firstly we create div element that we can use as
// tooltip container, it have absolute position and
// visibility: hidden by default

var tooltip = d3.select("body")
  .append("div")
  .attr('class', 'tooltip');

var svg = d3.select("body")
  .append("svg")
  .attr("width", w)
  .attr("height", h);

// here we add some circles on the page

var circles = svg.selectAll("circle")
  .data(dataset)
  .enter()
  .append("circle");

circles.attr("cx", function(d, i) {
    return (i * 50) + 25;
  })
  .attr("cy", h / 2)
  .attr("r", function(d) {
    return d;
  })
  
  // we define "mouseover" handler, here we change tooltip
  // visibility to "visible" and add appropriate test
  
  .on("mouseover", function(d) {
    return tooltip.style("visibility", "visible").text('radius = ' + d);
  })
  
  // we move tooltip during of "mousemove"
  
  .on("mousemove", function() {
    return tooltip.style("top", (event.pageY - 30) + "px")
      .style("left", event.pageX + "px");
  })
  
  // we hide our tooltip on "mouseout"
  
  .on("mouseout", function() {
    return tooltip.style("visibility", "hidden");
  });
.tooltip {
    position: absolute;
    z-index: 10;
    visibility: hidden;
    background-color: lightblue;
    text-align: center;
    padding: 4px;
    border-radius: 4px;
    font-weight: bold;
    color: orange;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.11.0/d3.min.js"></script>


Se qualcuno ha bisogno della punta dell'utensile per spostarsi rispetto alla posizione dell'oggetto. Come nel caso di un grafico ad albero. Si potrebbe desiderare di utilizzare return tooltip.style("top", (d.x + 40) + "px") .style("left", (d.y + 80) + "px");nel 'mousemove'attributo. L' d.xaiuto sposterà il tool-tip relativa all'oggetto, non l'intera pagina
Chandra Kanth
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.