wake-up-neo.net

Ruft die Breite des d3.js-SVG-Textelements ab, nachdem es erstellt wurde

Ich versuche, die Breite einer Reihe von text-Elementen zu ermitteln, die ich mit d3.js erstellt habe

So erstelle ich sie: 

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

Ich verwende dann die Breite, um rectangles die gleiche Größe wie die Boxen der text zu erstellen

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

Ich habe versucht, die Bbox-Methode von here zu verwenden, aber ich verstehe das nicht wirklich. Ich denke, dass die Auswahl des eigentlichen Elements darin liegt, dass ich wirklich falsch liege.

16
sanjaypoyzer

Ich würde die Länge Teil der ursprünglichen Daten machen:

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

und dann später

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

Sie können getBoundingClientRect() verwenden.

Beispiel:

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

edit: scheint für HTML-Elemente besser geeignet zu sein. Für SVG-Elemente können Sie stattdessen getBBbox () verwenden.

4
Liran Brimer

d3.selectAll gibt eine selection zurück. Sie können jedes elements erhalten, indem Sie durch das Array in der _groups-Eigenschaft navigieren. Wenn Sie die Breite eines Rechtecks ​​bestimmen, können Sie dessen Index verwenden, um das entsprechende Textelement abzurufen:

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

Die _groups-Eigenschaft der Auswahl von d3 verfügt über eine Liste von Knoten unter [0]. Diese Liste enthält alle ausgewählten elements , auf die Sie per Index zugreifen können. Es ist wichtig, dass Sie das SVG Element erhalten, damit Sie die getComputedTextLength-Methode verwenden können.

Vielleicht möchten Sie auch die rect-Elemente erstellen, dann die text-Elemente und dann zu den Rechtecken zurückkehren, um das width-Attribut zu bearbeiten, sodass sich die text-Elemente über den Rechtecken befinden (falls Sie die Rechtecke füllen möchten) mit Farbe).

Update:

In der Regel wird jedoch bevorzugt, dass Sie nicht auf _groups zugreifen. Eine sicherere Methode zum Ermitteln der Breite des übereinstimmenden Textelements wäre:

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

Wenn Sie node verwenden, wird das Element sicher abgerufen, und der Filter findet das Textelement, das dem Index entspricht.

0
M. Davis