David Merritt
David Merritt

Reputation: 25

Using d3 to generate rect that fits text size

Lars Kotthof has a good explanation here of how to create SVG elements that correspond to size of text. However, I'm looking to do this dynamically with data pulled from JSON or CSV.

JS Fiddle here.

    svg.selectAll('rect')
       .data(states.features)
       .enter()
       .append('rect')
          .attrs({
            x: function(d) { return path.centroid(d)[0] - 50; },
            y: function(d) { return path.centroid(d)[1] - 13; },
            'text-anchor': 'middle',
            'width': 100,
            'height': 18,
            'fill': 'rgba(232, 232, 232, 0.8)',
            'opacity': 1,
            'rx': 7,
            'ry': 7
         }); 

    svg.selectAll('text')
       .data(states.features)
       .enter()
       .append('text')
          .text(function(d) { return d.properties.name; })
          .attrs({
            x: function(d) { return path.centroid(d)[0]; },
            y: function(d) { return path.centroid(d)[1]; },
            'text-anchor': 'middle',
            'font-size': '7pt',
            'fill': 'rgb(25,25,25)',
            'opacity': 1
         });   

The concept I'm not grasping is how I can write a function, similar to Lars's, that creates both the <rect> and the <text> and uses the dimensions of the text to determine the dimensions of the rectangle.

Upvotes: 1

Views: 1710

Answers (1)

Nick
Nick

Reputation: 16576

Here's a solution and associated JS Fiddle. Basically what I did is assigned corresponding IDs to each rect and text, and then after the texts were generated, went adjusted the rect size based on the text. Additionally, the x position of the text had to be adjusted accordingly as well.

svg.selectAll('rect')
   .data(states.features)
   .enter()
   .append('rect')
      .attrs({
        y: function(d) { return path.centroid(d)[1] - 13; },
        'text-anchor': 'middle',
        'width': 100,
        'height': 18,
        'fill': 'rgba(232, 232, 232, 0.8)',
        'opacity': 1,
        'rx': 7,
        'ry': 7
     }); 

svg.selectAll('text')
   .data(states.features)
   .enter()
   .append('text')
      .text(function(d) { return d.properties.name; })
      .attrs({
        x: function(d) { return path.centroid(d)[0]; },
        y: function(d) { return path.centroid(d)[1]; },
        'text-anchor': 'middle',
        'font-size': '7pt',
        'fill': 'rgb(25,25,25)',
        'opacity': 1,
        id: function(d) { return 'text' + d.id }
     });   

svg.selectAll('rect')
    .attr('width', function(d) { return document.getElementById('text'+d.id).getBBox().width; })
    .attr('x', function(d) { return path.centroid(d)[0] - document.getElementById('text'+d.id).getBBox().width / 2; });

Upvotes: 3

Related Questions