web-dev-qa-db-fra.com

Obtenir la largeur de l'élément de texte SVG d3.js après sa création

J'essaie d'obtenir la largeur d'un tas d'éléments text que j'ai créés avec d3.js

Voici comment je les crée: 

var nodesText = svg.selectAll("text")
           .data(dataset)
           .enter()
           .append("text")
           .text(function(d) {
                return d.name;
           })
          .attr("x", function(d, i) {
                return i * (w / dataset.length);
           })
          .attr("y", function(d) {
                return 45;
          });

J'utilise ensuite la largeur pour créer rectangles la même taille que les cases text

var nodes = svg.selectAll("rect")
            .data(dataset)
            .enter()
            .append("rect")
            .attr("x", function(d, i) {
                return i * (w / dataset.length);
            })
            .attr("y", function(d) {
                return 25;
            })
            .attr("width", function(d, i) {
              //To Do: find width of each text element, after it has been generated
              var textWidth = svg.selectAll("text")
                  .each(function () {
                      return d3.select(this.getComputedTextLength());
                  });
                console.log(textWidth);
                return textWidth;
            })
            .attr("height", function(d) {
                return 30;
            })

J'ai essayé d'utiliser la méthode Bbox de ici mais je ne la comprends pas vraiment. Je pense que la sélection de l'élément réel est l'endroit où je me trompe vraiment.

16
sanjaypoyzer

Je voudrais faire la longueur des données d'origine:

var nodesText = svg.selectAll("text")
       .data(dataset)
       .enter()
       .append("text")
       .text(function(d) {
            return d.name;
       })
      .attr("x", function(d, i) {
            return i * (w / dataset.length);
       })
      .attr("y", function(d) {
            return 45;
      })
      .each(function(d) {
        d.width = this.getBBox().width;
      });

et plus tard

var nodes = svg.selectAll("rect")
        .data(dataset)
        .enter()
        .append("rect")
        .attr("width", function(d) { return d.width; });
11
Lars Kotthoff

Vous pouvez utiliser getBoundingClientRect()

Exemple:

.style('top', function (d) {
     var currElemHeight = this.getBoundingClientRect().height;
}

edit: semble plus approprié pour les éléments HTML. pour les éléments SVG, vous pouvez utiliser getBBbox () à la place.

4
Liran Brimer

d3.selectAll renvoie un sélection. Vous pouvez obtenir chacun des éléments en parcourant le tableau dans la propriété _groups. Lorsque vous déterminez la largeur d'un rectangle, vous pouvez utiliser son index pour obtenir l'élément de texte correspondant:

.attr('width', function (d, i) {
    var textSelection = d3.selectAll('text');
    return textSelection._groups[0][i].getComputedTextLength();
});

La propriété _groups de la sélection de d3 a une liste de nœuds à [0]. Cette liste contient tous les éléments} sélectionnés, auxquels vous pouvez accéder par index. Il est important que vous obteniez le SVG element pour pouvoir utiliser la méthode getComputedTextLength.

Vous pouvez également envisager de créer d'abord les éléments rect, puis les éléments text, puis de revenir aux rectangles pour modifier l'attribut width, de sorte que les éléments text soient au-dessus des rectangles (au cas où vous voudriez remplir les rectangles avec la couleur).

Mettre à jour:

Cependant, il est généralement préférable de ne pas accéder à _groups. Un moyen plus sûr d'obtenir la largeur de l'élément de texte correspondant serait:

.attr('width', function (d, i) {
    return d3.selectAll('text').filter(function (d, j) { return i === j; })
        .node().getComputedTextLength(); 
});

Utiliser node récupère en toute sécurité l'élément et le filtre trouvera l'élément de texte qui correspond à l'index.

0
M. Davis