Reputation: 25
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.
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
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