2012-03-27 9 views
31

Ich habe Probleme mit D3-Ereignissen und Versandfunktionen zu verstehen. Ich habe ein Diagrammbeispiel, an dem ich gearbeitet habe: "Vertical Bar Charts With Legends".Wie man D3 Events richtig hinzufügt und benutzt?

Das Zeichnen der Diagramme und der Legenden war einfach genug, aber ich möchte die Möglichkeit hinzufügen, jeden Balken hervorzuheben, während ich mit der Maus über die zugehörige Textlegende lege, die sich rechts vom Diagramm befindet.

Ich habe alle Event-Dokumentation gelesen und sogar eine Reihe von Beispielen betrachtet, von denen die meisten ziemlich kompliziert sind, aber mir scheint etwas zu fehlen. Würde jemand wissen, wie man die Mouseover-Funktionalität der Textlegende am besten bewerkstelligt, die Ereignisse auslöst, um die Farben der entsprechenden vertikalen Balken automatisch zu ändern?

Antwort

60

Diese Frage ist ähnlich der one you posted in der d3-js Google Group. Ohne zu wiederholen, was ich dort geschrieben habe, möchte ich wiederholen, dass Sie wahrscheinlich d3.dispatch nicht möchten; Dies ist für benutzerdefinierte Ereignisabstraktionen (wie Pinsel und Verhalten) gedacht. Es wird einfacher sein, native Ereignisse zu verwenden.

Wenn Sie Ihre Legende wollen die Farbe der entsprechenden Leiste mit der Maus darüber zu ändern, dann Bruchs das Problem in Schritten:

  1. Detect Mouseover auf die Legende.
  2. Wählen Sie die entsprechende Leiste aus.
  3. Ändern Sie die Füllfarbe des Balkens.

Verwenden Sie zuerst selection.on für „Mouseover“ Ereignisse auf dem Legendenelement zu hören. Ihre Listener-Funktion wird aufgerufen, wenn Sie mit der Maus über ein Legendenelement gehen. Sie wird mit zwei Argumenten aufgerufen: den Daten (d) und dem Index (i). Sie können diese Informationen verwenden, um den entsprechenden Balken über d3.select auszuwählen. Zuletzt verwenden Sie selection.style, um den Füllstil mit der neuen Farbe zu ändern.

Wenn Sie nicht sicher sind, wie Sie den entsprechenden Balken bei Legendenmouseover auswählen, gibt es normalerweise mehrere Optionen. Die einfachste Methode ist die Auswahl nach Index unter der Annahme, dass die Anzahl der Legendenelemente und die Anzahl der Rect-Elemente identisch sind und in derselben Reihenfolge liegen. In diesem Fall, wenn eine lokale Variable rect die rect Elemente enthält, könnte man sagen:

function mouseover(d, i) { 
    d3.select(rect[0][i]).style("fill", "red"); 
} 

Wenn Sie nicht auf den Index verlassen wollen, eine weitere Option für die Anpassungsleiste auf identische Daten basieren zu scannen ist. Dies verwendet selection.filter:

function mouseover(d, i) { 
    rect.filter(function(p) { return d === p; }).style("fill", "red"); 
} 

Eine weitere Option ist jede rect eine eindeutige ID zu geben, und wählen Sie dann von id. Zum Beispiel bei der Initialisierung, könnte man sagen:

rect.attr("id", function(d, i) { return "rect-" + i; }); 

Dann Sie die rect von ID mit der Maus darüber wählen könnten:

function mouseover(d, i) { 
    d3.select("#rect-" + i).style("fill", "red"); 
} 

Das obige Beispiel ersonnen, da ich den Index verwendet, um die ID zu erzeugen Attribut (in diesem Fall ist es einfacher und schneller, die erste Technik der Auswahl nach Index zu verwenden). Ein realistischeres Beispiel wäre, wenn Ihre Daten eine Namenseigenschaft hätten; Sie könnten dann d.name verwenden, um das ID-Attribut zu generieren, und ebenfalls nach ID auswählen. Sie können auch nach anderen Attributen oder Klassen auswählen, wenn Sie keine eindeutige ID generieren möchten.

+0

Hallo Mike, vielen Dank für Ihre Hilfe auf diesem Zeug. D3 ist eine großartige Technologie und ich genieße es, sie zu lernen. - Frank –

+0

FWIW Dieses Beispiel könnte einfach durch Hinzufügen einer: hover CSS-Regel zu den fraglichen SVG-Elementen implementiert werden. –

+1

@HerbCaudill A: Die Hover-Regel ist in diesem Fall zu einschränkend: In diesem Beispiel wird veranschaulicht, wie andere Elemente als das Steuerelement geändert werden, für das die Option aktiviert ist (z. B. Legende in Balken). A: Hover-Regel funktioniert nur, wenn die Elemente, die Sie ändern möchten, dieselben sind, die sich befinden (z. B. Legende). Siehe meine andere Antwort zu [Auswahl und Änderung verwandter Elemente] (http://stackoverflow.com/questions/11206015/clicking-a-node-in-d3-from-a-button-outside-the-svg/11211391). – mbostock

6

Mikes Antwort ist großartig.

habe ich es mit diesem kommt für eine Zelle in einem Raster Auswahl wurde ich Zeichnung:

.on('click', (d, i) -> 
     console.log("X:" + d.x, "Y:" + d.y) #displays the cell x y location 
     d3.select(this).style("fill", "red"); 

Also, wenn ich die Daten am Eintritt in mir den Ereignis-Listener hinzugefügt und mit d3.select (this) .

Siehe den Code in Zusammenhang unter:

vis.selectAll("rect") 
    .data(singleArray) 
    .enter().append("svg:rect") 
    .attr("stroke", "none") 
    .attr("fill", (d) -> 
     if d.lifeForm 
     return "green" 
     else 
     return "white") 
    .attr("x", (d) -> xs(d.x)) 
    .attr("y", (d) -> ys(d.y)) 
    .attr("width", cellWidth) 
    .attr("height", cellHeight) 
    .on('click', (d, i) -> 
     console.log("X:" + d.x, "Y:" + d.y) 
     d3.select(this).style("fill", "red"); 
     return 
    )