90 votes

Mise à jour de l'indice Z des éléments SVG avec D3

Ce qui est un moyen efficace pour apporter un élément SVG vers le haut de l'axe z, à l'aide de la D3 de la bibliothèque?

Mon scénario est un graphique qui met en évidence (par l'ajout d'un stroke de la path) lorsque la souris est sur une pièce donnée. Le bloc de code pour la génération de mon tableau ci-dessous:

svg.selectAll("path")
    .data(d)
  .enter().append("path")
    .attr("d", arc)
    .attr("class", "arc")
    .attr("fill", function(d) { return color(d.name); })
    .attr("stroke", "#fff")
    .attr("stroke-width", 0)
    .on("mouseover", function(d) {
        d3.select(this)
            .attr("stroke-width", 2)
            .classed("top", true);
            //.style("z-index", 1);
    })
    .on("mouseout", function(d) {
        d3.select(this)
            .attr("stroke-width", 0)
            .classed("top", false);
            //.style("z-index", -1);
    });

J'ai essayé quelques options, mais pas de chance jusqu'à présent. À l'aide de style("z-index") et en appelant classed les deux n'ont pas de travail.

Le "top" de la classe est définie comme suit dans mon CSS:

.top {
    fill: red;
    z-index: 100;
}

L' fill déclaration est là pour s'assurer que je savais que c'était allumer/éteindre correctement. Il est.

J'ai entendu à l'aide de sort est une option, mais je suis pas clair sur la façon dont il sera mis en œuvre pour amener les "sélectionnés" l'élément vers le haut.

Mise à JOUR:

Je fixe mon cas en particulier avec le code suivant, qui ajoute un nouvel arc pour la SVG sur l' mouseover évènement pour montrer une évidence.

svg.selectAll("path")
    .data(d)
  .enter().append("path")
    .attr("d", arc)
    .attr("class", "arc")
    .style("fill", function(d) { return color(d.name); })
    .style("stroke", "#fff")
    .style("stroke-width", 0)
    .on("mouseover", function(d) {
        svg.append("path")
          .attr("d", d3.select(this).attr("d"))
          .attr("id", "arcSelection")
          .style("fill", "none")
          .style("stroke", "#fff")
          .style("stroke-width", 2);
    })
    .on("mouseout", function(d) {
        d3.select("#arcSelection").remove();
    });

94voto

notan3xit Points 820

Comme expliqué dans les autres réponses, SVG ne pas avoir une notion de l'un z-index. Au lieu de cela, l'ordre des éléments dans le document détermine l'ordre dans le dessin.

En dehors de réordonner les éléments manuellement, il est une autre façon pour certaines situations:

Travailler avec D3 vous avez souvent de certains types d'éléments qui devraient toujours être dessiné sur d'autres types d'éléments.

Par exemple, lors de la présentation des graphiques, des liens doivent toujours être placé au-dessous des nœuds. Plus généralement, certains éléments de décor ont généralement besoin d'être placé au-dessous de tout le reste, alors que certains des faits saillants et des superpositions doit être placé au-dessus.

Si vous avez ce genre de situation, j'ai trouvé que la création d' un groupe de parents d'éléments en faveur de ces groupes d'éléments est la meilleure façon d'aller. En SVG, vous pouvez utiliser l' g élément. Par exemple, si vous avez des liens qui doivent toujours être placé au-dessous des nœuds, procédez de la manière suivante:

svg.append("g").attr("id", "links")
svg.append("g").attr("id", "nodes")

Maintenant, lorsque vous peignez vos liens et de nœuds, sélectionnez comme suit (les sélecteurs en commençant par # référence de l'identifiant de l'élément):

svg.select("#links").selectAll(".link")
// add data, attach elements and so on

svg.select("#nodes").selectAll(".node")
// add data, attach elements and so on

Maintenant, tous les liens seront toujours ajoutées structurellement avant que tous les éléments de nœuds. Ainsi, le SVG montrera tous les liens au-dessous de tous les nœuds, peu importe combien de fois et dans quel ordre vous d'ajouter ou de supprimer des éléments. Bien sûr, tous les éléments de même type (c'est à dire dans le même conteneur) seront toujours soumises à l'ordre dans lequel ils ont été ajoutés.

56voto

futurend Points 154

L'une des solutions présentées par le développeur est la suivante: "utilisez l'opérateur de tri de D3 pour réorganiser les éléments". (voir https://github.com/mbostock/d3/issues/252 )

Dans cette optique, on pourrait trier les éléments en comparant leurs données, ou leurs positions s’il s’agissait d’éléments sans données:

 .on("mouseover", function(d) {
    svg.selectAll("path").sort(function (a, b) { // select the parent and sort the path's
      if (a.id != d.id) return -1;               // a is not the hovered element, send "a" to the back
      else return 1;                             // a is the hovered element, bring "a" to the front
  });
})
 

27voto

swenedo Points 764

Comme SVG n'a pas d'index Z mais utilise l'ordre des éléments DOM, vous pouvez l'amener au premier plan en:

 this.parentNode.appendChild(this);
 

Vous pouvez ensuite utiliser la fonction d'insertion de d3 pour la remettre sur mouseout .

13voto

meetamit Points 7645

SVG ne fait pas de z-index. Z-ordre est dicté par l'ordre du SVG éléments du DOM dans leur conteneur.

Aussi loin que je puisse dire (et j'ai essayé cette une couple de fois dans le passé), D3 n'est pas de fournir des méthodes pour le détachement et le rattachement à un seul élément pour l'amener à l'avant ou que sais-je encore.

Il y a un .order() méthode, qui bouleverse les nœuds pour correspondre à l'ordre qu'ils apparaissent dans la sélection. Dans votre cas, vous devez apporter un seul élément à l'avant. Donc, techniquement, vous pourriez complexe de la sélection avec l'élément souhaité à l'avant (ou à la fin, ne peut pas se rappeler qui est le plus en haut), puis appelez order() sur il.

Ou, vous pouvez passer de d3 pour cette tâche et utiliser du JS (jQuery) pour ré-insérer le seul élément du DOM.

4voto

lk145 Points 156

J'ai mis en place futurend de la solution dans mon code et cela a fonctionné, mais avec le grand nombre d'éléments que j'ai été en utilisant, il était très lent. Voici la méthode alternative à l'utilisation de jQuery, qui a travaillé plus vite pour mon particulier de visualisation. Il s'appuie sur le svgs vous voulez sur le dessus d'avoir une classe en commun (dans mon exemple, la classe est noté dans mon jeu de données que d.la clé). Dans mon code il y a un <g> avec la catégorie "bureaux" qui contient tous les SVGs je suis en train de redéfinir l'organisation.

.on("mouseover", function(d) {
    var pts = $("." + d.key).detach();
    $(".locations").append(pts);
 });

Ainsi, lorsque vous passez la souris sur un point particulier de données, le code trouve toutes les autres points de données avec SVG des éléments du DOM avec cette classe particulière. Puis il se détache et ré-insère le SVG DOM éléments associés à ces points de données.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X