web-dev-qa-db-fra.com

Comment ajouter et utiliser correctement les événements D3?

J'ai du mal à comprendre l'utilisation des événements D3 et des fonctions de répartition. J'ai un exemple de graphique sur lequel j'ai travaillé appelé: " Vertical Bar Charts With Legends ."

Dessiner les graphiques et les légendes a été assez facile, mais j'aimerais ajouter la possibilité de mettre en surbrillance chaque barre lorsque je passe la souris sur sa légende de texte corrélative, située à droite du graphique.

J'ai lu toute la documentation de l'événement et j'ai même examiné un certain nombre d'exemples, dont la plupart sont assez compliqués, mais il me semble manquer quelque chose. Quelqu'un sait-il comment utiliser au mieux la fonctionnalité de survol de la légende de texte qui distribue les événements pour changer automatiquement les couleurs des barres verticales correspondantes?

32

Cette question est similaire à celle que vous avez publiée dans le groupe Google d3-js. Sans reproduire ce que j'ai écrit là-bas, je réitère que vous ne voulez probablement pas d3.dispatch; destiné aux abstractions d'événements personnalisées (telles que les pinceaux et les comportements). Il sera plus simple d'utiliser des événements natifs.

Si vous voulez que votre légende change la couleur de la barre correspondante au survol de la souris, décomposez le problème en étapes:

  1. Détectez le survol de la légende.
  2. Sélectionnez la barre correspondante.
  3. Modifiez la couleur de remplissage de la barre.

Tout d'abord, utilisez selection.on pour écouter les événements de "survol de la souris" sur les éléments de légende. Votre fonction d'écoute sera appelée lorsque la souris survolera un élément de légende et sera appelée avec deux arguments: les données (d) et l'index (i). Vous pouvez utiliser ces informations pour sélectionner la barre correspondante via d3.select . Enfin, utilisez selection.style pour changer le style "fill" avec la nouvelle couleur.

Si vous ne savez pas comment sélectionner la barre correspondante lors du survol de la légende, il existe généralement plusieurs options. Le plus simple est de sélectionner par index, en supposant que le nombre d'éléments de légende et le nombre d'éléments rect sont identiques et qu'ils sont dans le même ordre. Dans ce cas, si une variable locale rect contient les éléments rect, vous pouvez dire:

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

Si vous ne voulez pas vous fier à l'index, une autre option consiste à rechercher la barre correspondante sur la base de données identiques. Cela utilise selection.filter :

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

Encore une autre option consiste à donner à chaque rect un ID unique, puis à sélectionner par id. Par exemple, lors de l'initialisation, vous pourriez dire:

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

Ensuite, vous pouvez sélectionner le rect par id lors du survol de la souris:

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

L'exemple ci-dessus est artificiel puisque j'ai utilisé l'index pour générer l'attribut id (dans ce cas, il est plus simple et plus rapide d'utiliser la première technique de sélection par index). Un exemple plus réaliste serait si vos données avaient une propriété de nom; vous pouvez alors utiliser d.name pour générer l'attribut id et également sélectionner par id. Vous pouvez également sélectionner d'autres attributs ou classe, si vous ne souhaitez pas générer un identifiant unique.

60
mbostock

La réponse de Mike est excellente.

Je l'ai utilisé pour trouver une cellule dans une grille que je dessinais:

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

Ainsi, lorsque j'entre les données dans, j'ai ajouté l'écouteur d'événements et en utilisant d3.select (this).

Voir le code dans le contexte ci-dessous:

 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
    ) 
6
ChickenFur