Reputation: 163
How do I give padding on top/bottom/left/right to text that is contained inside a D3 rect component? I was only able to give it to the left side of text, though I am not sure that is indeed the right way. I have been struggling over this for a couple of days and it would be great if anyone could help me figure out a way to do it.
Below is the example code I have so far ->
https://jsfiddle.net/passionateCoder/4uf3h2L8/
<!DOCTYPE html>
<html>
<head>
<!-- <script
data-require="[email protected]"
data-semver="3.5.3"
src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"
></script> -->
<script src="https://d3js.org/d3.v6.min.js"></script>
</head>
<body>
<script>
function wrap(text, width) {
text.each(function () {
var text = d3.select(this),
words = text.text().split(/\s+/).reverse(),
word,
line = [],
lineNumber = 0,
lineHeight = 1.1, // ems
y = text.attr('y'),
dy = parseFloat(text.attr('dy')),
tspan = text
.text(null)
.append('tspan')
.attr('x', 10)
.attr('y', y)
.attr('dy', dy + 'em');
while ((word = words.pop())) {
line.push(word);
tspan.text(line.join(' '));
if (tspan.node().getComputedTextLength() > width) {
line.pop();
tspan.text(line.join(' '));
line = [word];
tspan = text
.append('tspan')
.attr('x', 10)
.attr('y', y)
.attr('dy', ++lineNumber * lineHeight + dy + 'em')
.text(word);
}
}
});
}
var svg = d3
.select('body')
.append('svg')
.attr('width', 500)
.attr('height', 5000);
var longText =
'Now is the time for all good men to come to the aid of their countryNow is the time for all good men to come to the aid of their countryNow is the time for all good men to come to the aid of their countryNow is the time for all good men to come to the aid of their country';
var totHeight = 0;
drawRect();
function drawRect() {
var someWidth = 212;
var g = svg
.append('g')
.attr('transform', 'translate(20,' + totHeight + ')');
var rect = g
.append('rect')
.style('fill', 'steelblue')
.attr('width', someWidth)
.attr('height', 1);
var txt = g
.append('text')
.text(longText)
.attr('x', 4)
.attr('y', 10)
.attr('dy', '.71em')
.style('fill', 'white')
.call(wrap, someWidth);
var height = txt.node().getBBox().height + 25;
totHeight += height + 10;
rect.attr('height', height);
}
</script>
</body>
</html>
Upvotes: 2
Views: 1443
Reputation: 102174
Firstly, in the wrap
function, I'd advise you to set the x
attribute according to the attribute you used in the text selection:
x = text.attr('x')
After that, it's simply a matter of subtracting both margins from someWidth
. For instance, since you're using 14 (10 + 4):
var txt = g.append('text')
//etc...
.attr('x', 14)
.call(wrap, someWidth - 28);
Here is your code with those changes:
function wrap(text, width) {
text.each(function() {
var text = d3.select(this),
words = text.text().split(/\s+/).reverse(),
word,
line = [],
lineNumber = 0,
lineHeight = 1.1, // ems
y = text.attr('y'),
x = text.attr('x')
dy = parseFloat(text.attr('dy')),
tspan = text
.text(null)
.append('tspan')
.attr('x', x)
.attr('y', y)
.attr('dy', dy + 'em');
while ((word = words.pop())) {
line.push(word);
tspan.text(line.join(' '));
if (tspan.node().getComputedTextLength() > width) {
line.pop();
tspan.text(line.join(' '));
line = [word];
tspan = text
.append('tspan')
.attr('x', x)
.attr('y', y)
.attr('dy', ++lineNumber * lineHeight + dy + 'em')
.text(word);
}
}
});
}
var svg = d3
.select('body')
.append('svg')
.attr('width', 500)
.attr('height', 5000);
var longText =
'Now is the time for all good men to come to the aid of their countryNow is the time for all good men to come to the aid of their countryNow is the time for all good men to come to the aid of their countryNow is the time for all good men to come to the aid of their country';
var totHeight = 0;
drawRect();
function drawRect() {
//var someWidth = randomIntFromInterval(40, 300);
var someWidth = 212;
var g = svg
.append('g')
.attr('transform', 'translate(20,' + totHeight + ')');
var rect = g
.append('rect')
.style('fill', 'steelblue')
.attr('width', someWidth)
.attr('height', 1);
var txt = g
.append('text')
.text(longText)
.attr('x', 14)
.attr('y', 10)
.attr('dy', '.71em')
.style('fill', 'white')
.call(wrap, someWidth - 28);
var height = txt.node().getBBox().height + 25;
totHeight += height + 10;
rect.attr('height', height);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div id="body"></div>
Upvotes: 1