Get width of d3.js SVG text element after it's created

后端 未结 3 1614
梦毁少年i
梦毁少年i 2021-02-19 00:43

I\'m trying to get the widths of a bunch of text elements I have created with d3.js

This is how I\'m creating them:

var nodesText = svg.sel         


        
相关标签:
3条回答
  • 2021-02-19 01:06

    I would make the length part of the original data:

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

    and then later

    var nodes = svg.selectAll("rect")
            .data(dataset)
            .enter()
            .append("rect")
            .attr("width", function(d) { return d.width; });
    
    0 讨论(0)
  • 2021-02-19 01:08

    You can use getBoundingClientRect()

    Example:

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

    edit: seems like its more appropriate for HTML elements. for SVG elements you can use getBBbox() instead.

    0 讨论(0)
  • 2021-02-19 01:12

    d3.selectAll returns a selection. You can get each of the elements by navigating through the array in the _groups property. When you are determining the width of a rectangle, you can use its index to get the corresponding text element:

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

    The _groups property of d3's selection has a list of nodes at [0]. This list contains all of the selected elements, which you can access by index. It's important that you get the SVG element so that you can use the getComputedTextLength method.

    You may also want to consider creating the rect elements first, then the text elements, and then going back to the rectangles to edit the width attribute, so that the text elements are on top of the rectangles (in case you want to fill the rectangles with color).

    Update:

    It's typically preferred that you don't access _groups, though, so a safer way to get the matching text element's width would be:

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

    Using node safely retrieves the element, and filter will find the text element which matches index.

    0 讨论(0)
提交回复
热议问题