Daten beim Mouseover des Kreises anzeigen

162

Ich habe eine Reihe von Daten, die ich in einer Streuung zeichne. Wenn ich mit der Maus über einen der Kreise fahre, möchte ich, dass Daten angezeigt werden (z. B. x-, y-Werte, möglicherweise mehr). Folgendes habe ich versucht:

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

Ich vermute, ich muss informativer darüber sein, welche Daten eingegeben werden sollen.

ScottieB
quelle
1
Ich habe auch versucht: vis.selectAll ("Kreis"). Jede (Funktion (d) {vis.append ("svg: text"). Attr ("x", dx) .attr ("y", dy) .text (Funktion (d) {return dx;});}); leider ohne Erfolg.
ScottieB

Antworten:

181

Ich gehe davon aus, dass Sie einen Tooltip wünschen. Der einfachste Weg, dies zu tun, besteht darin svg:title, jedem Kreis ein Element anzuhängen , da der Browser dafür sorgt, dass der Tooltip angezeigt wird und Sie den Mauszeiger nicht benötigen. Der Code wäre so etwas wie

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

Wenn Sie schickere Tooltips wünschen, können Sie beispielsweise beschwipst verwenden. Siehe hier für ein Beispiel.

Lars Kotthoff
quelle
3
Ich mag beschwipst. Mein einziges Problem ist jetzt, dass es auf die obere linke Ecke des Kreises zeigt und nicht auf die Kante wie in dieser Demo. Ich finde keinen offensichtlichen Grund dafür. jsfiddle.net/scottieb/JwaaV (beschwipst ganz unten)
ScottieB
Dass jsfiddle keine Tooltips zu haben scheint?
Lars Kotthoff
Sie können versuchen, den Tooltip zu einem Tooltip hinzuzufügen, den svg:gSie mit dem tatsächlichen Kreis überlagern, aber keine Breite und Höhe angeben. Derzeit wird der Begrenzungsrahmen verwendet und der Tooltip am Rand platziert. Das Herumspielen mit den Optionen von tipsy könnte ebenfalls hilfreich sein.
Lars Kotthoff
1
Es scheint nicht mehr zu funktionieren. Außerdem habe ich ein Beispiel mit svg: title gefunden, das fehlschlägt: bl.ocks.org/ilyabo/1339996
nos
1
@nos Funktioniert für mich.
Lars Kotthoff
144

Ein wirklich guter Weg, um einen Tooltip zu erstellen, wird hier beschrieben: Einfaches D3-Tooltip-Beispiel

Sie müssen ein div anhängen

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

Dann können Sie es einfach mit umschalten

.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.pageYist die aktuelle Mauskoordinate.

Wenn Sie den Text ändern möchten, können Sie ihn verwenden tooltip.text("my tooltip text");

Arbeitsbeispiel

Pwdr
quelle
4
Können Sie Daten an diesen Tooltip binden?
Jorge Leitao
2
Afaik können Sie Daten an jedes DOM-Element binden.
Pwdr
Um die Daten daran zu binden, fügen Sie einfach d wie folgt in die Klammer ein: function (d) {... und ändern Sie den Text nach Ihren Wünschen. Angenommen, Sie haben einen Namen: tooltip.text (d.name):
thatOneGuy
39

Dafür gibt es eine großartige Bibliothek, die ich kürzlich entdeckt habe. Es ist einfach zu bedienen und das Ergebnis ist ganz ordentlich: d3-tip.

Sie können hier ein Beispiel sehen :

Geben Sie hier die Bildbeschreibung ein

Grundsätzlich müssen Sie nur ( index.js ) herunterladen und das Skript einschließen:

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

und folgen Sie dann den Anweisungen von hier (gleicher Link wie Beispiel)

Aber für Ihren Code wäre es so etwas wie:

Definieren Sie die Methode:

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

erstelle deine svg (wie du es schon tust)

var svg = ...

Rufen Sie die Methode auf:

svg.call(tip);

Tipp zu deinem Objekt hinzufügen:

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

Vergessen Sie nicht, das CSS hinzuzufügen:

<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>
DanielX2010
quelle
2
Der neueste d3-tip unterstützt d3v4 einwandfrei. Es ist nicht offensichtlich, wenn Sie googeln, aber es funktioniert gut für mich mit d3v4.
Moodboom
6

Sie können die Daten, die im Mouseover verwendet werden sollen, wie folgt übergeben: Das Mouseover-Ereignis verwendet eine Funktion mit Ihren zuvor bearbeiteten enterDaten als Argument (und den Index als zweites Argument), sodass Sie kein enter()zweites Mal verwenden müssen.

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)); 
});
danimal
quelle
Vielen Dank. Ich brauchte das wirklich d3.select(this), um die Form zu ändern und wusste nicht, wie ich die Instanz in eine Eingabe / Aktualisierung bekommen sollte.
Turbo
Sie verwenden einige Funktionen x () und y (), die in Ihrem Code nicht definiert sind. Ich denke das kann entfernt werden.
Robert
Sie wurden im OP
Danimal
5

Dieses kurze Beispiel zeigt, wie Sie in d3 benutzerdefinierte QuickInfos erstellen.

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>

Mikhail Shabrikov
quelle
Wenn jemand den Tooltip benötigt, um sich relativ zur Position des Objekts zu bewegen. Wie im Fall eines Baumgraphen. Möglicherweise möchten Sie return tooltip.style("top", (d.x + 40) + "px") .style("left", (d.y + 80) + "px");das 'mousemove'Attribut verwenden. Das d.xwird helfen, den Tooltip relativ zum Objekt zu bewegen, nicht zur gesamten Seite
Chandra Kanth