Skip to content

Instantly share code, notes, and snippets.

@nitaku
Last active April 28, 2022 08:04
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nitaku/8745933 to your computer and use it in GitHub Desktop.
Save nitaku/8745933 to your computer and use it in GitHub Desktop.
SVG text bounding box (with transform)

Same as the previous example, the bounding box of an SVG text element is used to highlight it with a yellow rectangle.

This time, the functionality is implemented with SVG transforms. The text is translated to its position, getBBox() is used in combination with getCTM() to obtain the original bounding box and the transformation matrix respectively. Then, the rect is created as before, but in addition the read transformation matrix is applied to it (see this StackOverflow post for more info).

(By reading the provided link on getBBox() pointing to the W3C spec, I got the impression that getBBox() should have returned the bounding box after the transform. I don't know if I am getting it wrong, but at least on Chrome 32 getCTM() is needed to make it work.)

width = 960
height = 500
### create the SVG ###
svg = d3.select('body').append('svg')
.attr('width', width)
.attr('height', height)
# create a text element
text = svg.append('text')
.text('Hello world!')
.attr('dy','0.35em')
.attr('transform', 'translate(480,250)')
# define a function to set the Transformation Matrix of an SVG element
setTM = (element, m) -> element.transform.baseVal.initialize(element.ownerSVGElement.createSVGTransformFromMatrix(m))
# obtain the text element's bounding box and Current Transformation Matrix
bbox = text[0][0].getBBox()
ctm = text[0][0].getCTM()
# insert a yellow rect beneath the text, to represent the bounding box
rect = svg.insert('rect','text')
.attr('x', bbox.x)
.attr('y', bbox.y)
.attr('width', bbox.width)
.attr('height', bbox.height)
# set the same transform on the rect
setTM(rect[0][0], ctm)
text {
font-size: 80px;
font-family: Georgia;
text-anchor: middle;
}
rect {
fill: yellow;
opacity: 0.3;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>SVG text bounding box (with transform)</title>
<link type="text/css" href="index.css" rel="stylesheet"/>
<script src="http://d3js.org/d3.v3.min.js"></script>
</head>
<body>
</body>
<script src="index.js"></script>
</html>
(function() {
var bbox, ctm, height, rect, setTM, svg, text, width;
width = 960;
height = 500;
/* create the SVG
*/
svg = d3.select('body').append('svg').attr('width', width).attr('height', height);
text = svg.append('text').text('Hello world!').attr('dy', '0.35em').attr('transform', 'translate(480,250)');
setTM = function(element, m) {
return element.transform.baseVal.initialize(element.ownerSVGElement.createSVGTransformFromMatrix(m));
};
bbox = text[0][0].getBBox();
ctm = text[0][0].getCTM();
rect = svg.insert('rect', 'text').attr('x', bbox.x).attr('y', bbox.y).attr('width', bbox.width).attr('height', bbox.height);
setTM(rect[0][0], ctm);
}).call(this);
text
font-size: 80px
font-family: Georgia
text-anchor: middle
rect
fill: yellow
opacity: 0.3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment