3

I know this has been asked here before but I'm encountering a very weird issue...

I'm trying to give arbitrarily sized text a coloured background. What I'm doing is: creating the text, calculating the coordinates and dimensions of the text, and then creating a rectangle with the same dimensions and coordinates, ensuring it's inserted before the text so it does not cover it up. I'm using d3 for all of this.

The issue is that sometimes the rectangle is slightly too thin, so some text sticks out the end (words ending in "s" seem to be the main offender, weirdly). The vertical placement of the rectangles are also slightly too high, so there's some blank space at the top, and any "dangling" letters like g, p, etc. extend beneath the rectangle.

See the following image:

enter image description here

Here's the code I'm using:

let textContainer = self.svg.append("g")
    .attr("id", "textContainer");

textContainer.append("text")
    .attr("x", xcoordinate)
    .attr("y", ycoordinate)
    .attr("text-anchor", "middle")
    .text(text);

let bBox = (textContainer.node() as any).getBBox();
textContainer.insert("rect", "#textContainer text")
    .attr("width", bBox.width)
    .attr("height", bBox.height)
    .attr("x", bBox.x)
    .attr("y", bBox.y)
    .attr("fill", "gray");

Why is this issue happening?

clb
  • 715
  • 9
  • 23
  • I hope this link might help you, [link](https://stackoverflow.com/questions/15500894/background-color-of-text-in-svg) – Rajesh Murugan Aug 21 '17 at 10:30
  • It seems like you have some CSS applied to your text nodes, compared to [this example](https://bl.ocks.org/mbostock/1160929) you seem to have a margin top and left applied that slightly moves your text out of the rect. – WhiteFangs Aug 21 '17 at 10:59
  • Do you have a fiddle which demonstrates the issue? – Gilsha Aug 21 '17 at 11:08
  • @Gilsha this demonstrates it slightly, though not as severe for some reason: https://jsfiddle.net/1fqL50xp/ I know it's slightly unusual to have a viewBox of "0 0 2 2", but I would have thought this shouldn't affect things seeing as the S stands for "scalable". :) – clb Aug 21 '17 at 11:35
  • You could try this instead: https://stackoverflow.com/questions/15500894/background-color-of-text-in-svg/31013492#31013492 – Robert Longson Aug 21 '17 at 11:49
  • 1
    Bug reported to Chrome: https://bugs.chromium.org/p/chromium/issues/detail?id=757436 Note that text-anchor="middle" makes the error worse. If you don't need that, you will get a more accurate box. – Paul LeBeau Aug 21 '17 at 13:33
  • @PaulLeBeau Thanks for reporting it! FWIW, I think the small viewBox might be causing it - here's your jsfiddle but with a larger viewBox: https://jsfiddle.net/f35cabo6/ Still a bug of course, but it may be worth including this information in the report? (if you're able to change it after submission) – clb Aug 21 '17 at 14:43

1 Answers1

1

The problem seems to be with the calculation of x and y positions for the rectangle. A slight miscalculation when it is relative to the text inside the view-box.

However, you can resolve this issue by moving the x and y position attributes to the container group element as shown below.

let textContainer = d3.select("svg").append("g").attr("id", "textContainer");

textContainer.attr("transform","translate(1,1)"); //Apply position coordinates here 

textContainer.append("text")
  .attr("x",0) //Sets to 0
  .attr("y",0) //Sets to 0
  .attr("text-anchor", "middle")
  .attr("font-size", 0.5)
  .text("Test");

let bBox = textContainer.node().getBBox();
textContainer.insert("rect", "#textContainer text")
  .attr("width", bBox.width)
  .attr("height", bBox.height)
  .attr("x", bBox.x)
  .attr("y", bBox.y)
  .attr("fill", "gray");
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<svg width="600" height="600" style="border: 1px solid black" viewBox="0 0 2 2">
</svg>

Still, this is not a perfect solution.

Gilsha
  • 14,431
  • 3
  • 32
  • 47