pre-computing size of svg:text objects

14,639 views
Skip to first unread message

frank

unread,
Aug 2, 2011, 2:17:59 AM8/2/11
to d3-js
Hi group,

Is there a way to calculate the size of a text object so, say, I can
draw a rectangle around the text element that fits nicely?

Jon Frost

unread,
Aug 2, 2011, 8:35:21 AM8/2/11
to d3...@googlegroups.com

Bixente

unread,
Aug 2, 2011, 10:52:34 AM8/2/11
to d3-js
Hi guys,

Thanks for the answer, I also tried to do something similar before. If
someone manages to use the links mentioned above with d3, I'd be happy
to see the result.

Thanks,

Bixente

On Aug 2, 2:35 pm, Jon Frost <jonfrost2...@gmail.com> wrote:
> The getBBox method works well for this:http://www.learnsvg.com/tutorials/tutorialScripting/example/getBBox.svg
> Here are some more SVG DOM methods available for text:http://www.learnsvg.com/tutorials/tutorialScripting/text.svg
>
> These helpful short articles on the subject:http://my.opera.com/MacDev_ed/blog/2009/01/21/getting-boundingbox-of-...http://my.opera.com/MacDev_ed/blog/getting-screen-boundingboxes-in-svg

frank

unread,
Aug 3, 2011, 12:00:45 AM8/3/11
to d3-js
Thanks Jon for the entire list of references! this exactly what I am
looking for - gonna go try it now :)

On Aug 2, 5:35 am, Jon Frost <jonfrost2...@gmail.com> wrote:
> The getBBox method works well for this:http://www.learnsvg.com/tutorials/tutorialScripting/example/getBBox.svg
> Here are some more SVG DOM methods available for text:http://www.learnsvg.com/tutorials/tutorialScripting/text.svg
>
> These helpful short articles on the subject:http://my.opera.com/MacDev_ed/blog/2009/01/21/getting-boundingbox-of-...http://my.opera.com/MacDev_ed/blog/getting-screen-boundingboxes-in-svg

Devang Mundhra

unread,
Aug 3, 2011, 10:21:11 PM8/3/11
to d3...@googlegroups.com
<svg:text>.getComputedTextLength()
Returns in pts (including all glyphs, character spacing etc..)

Bixente

unread,
Aug 21, 2011, 10:01:57 AM8/21/11
to d3-js
Hey,

Did someone manage to use getBBox combined with d3? If you have got
time would you be able to share an example?

Thanks a lot,

Bixente

Mike Bostock

unread,
Aug 21, 2011, 2:06:11 PM8/21/11
to d3...@googlegroups.com
There's not really much to explain, beyond calling getBBox on a node.
Here's an example:

http://bl.ocks.org/1160929

And the spec:

http://www.w3.org/TR/SVG/types.html#__svg__SVGLocatable__getBBox

Mike

Robert Monteverde

unread,
Aug 21, 2011, 2:19:07 PM8/21/11
to d3...@googlegroups.com
Hmm, I developed a similar functionality using jQuery and HTML elements. Its been working for svg (though I guess if there's minor differences to how a font renders from within svg to html, might be worth changing the code to use an SVG container for measurements.

String.prototype.width || (String.prototype.width = function(font) {
var f = font || '12px arial',
o = $('<div>' + this + '</div>')
.css({'position': 'absolute', 'float': 'left', 'visibility': 'hidden', 'font': f})
.appendTo($('body')),
w = o.width();

o.remove();

return w;
});


This is actually a slightly older implementation, I've also implemented this where instead of feeding it a font string, you could feed it a container, and it would take the font properties set on the container to do the measurement (pretty straight forward how to implement that into the above code).

To sum up converting this to use SVG, just have an invisible SVG container to do this in, OR you could use the SVG container you are using, and simply append, then remove, invisible text, using the getBBox for the measurement,

Its also easy to use this to implement a way to do automatic line breaks in SVG (and with a minor change you can implement a String.height() function as well. I use this for creating legends in the top right corner of my graphs.

Bob

________________________________________
From: d3...@googlegroups.com [d3...@googlegroups.com] on behalf of Mike Bostock [mbos...@cs.stanford.edu]
Sent: Sunday, August 21, 2011 2:06 PM
To: d3...@googlegroups.com
Subject: Re: pre-computing size of svg:text objects

http://bl.ocks.org/1160929

And the spec:

http://www.w3.org/TR/SVG/types.html#__svg__SVGLocatable__getBBox

Mike
This e-mail message, and any attachments, is intended only for the use of the individual or entity identified in the alias address of this message and may contain information that is confidential, privileged and subject to legal restrictions and penalties regarding its unauthorized disclosure and use. Any unauthorized review, copying, disclosure, use or distribution is strictly prohibited. If you have received this e-mail message in error, please notify the sender immediately by reply e-mail and delete this message, and any attachments, from your system. Thank you.

Bixente

unread,
Aug 22, 2011, 9:18:16 AM8/22/11
to d3-js
Thanks guys for your answer. I really appreciate it. One last thing if
you have got time. I have managed to implement getBBox with Mike's
method on a map but my box is not positioned correctly on my text.
More precisely, the upper right corner of my box is positioned on the
middle of my text. I don't know how to position the centre of the box
on the centre of my text... (if that makes sense)

See my code for NYC:

var text = svg.append("svg:text")
.attr("transform", function(d) { return "translate(" +
xy([-74,40.716667]) + ")"; } )
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.style("font", "300 24px Helvetica Neue")
.text("New York!");

var bbox = text.node().getBBox();

var rect = svg.append("svg:rect")
.attr("transform", function(d) { return "translate(" +
xy([-74,40.716667]) + ")"; } )
.attr("width", bbox.width)
.attr("height", bbox.height)
.style("fill", "#ccc")
.style("fill-opacity", ".3")
.style("stroke", "#666")
.style("stroke-width", "1.5px");




Thanks a lot,

Bixente




On Aug 21, 8:19 pm, Robert Monteverde <b...@novus.com> wrote:
> Hmm, I developed a similar functionality using jQuery and HTML elements.  Its been working for svg (though I guess if there's minor differences to how a font renders from within svg to html, might be worth changing the code to use an SVG container for measurements.
>
> String.prototype.width || (String.prototype.width = function(font) {
>   var f = font || '12px arial',
>       o = $('<div>' + this + '</div>')
>             .css({'position': 'absolute', 'float': 'left', 'visibility': 'hidden', 'font': f})
>             .appendTo($('body')),
>       w = o.width();
>
>   o.remove();
>
>   return w;
>
> });
>
> This is actually a slightly older implementation, I've also implemented this where instead of feeding it a font string, you could feed it a container, and it would take the font properties set on the container to do the measurement (pretty straight forward how to implement that into the above code).
>
> To sum up converting this to use SVG, just have an invisible SVG container to do this in, OR you could use the SVG container you are using, and simply append, then remove, invisible text, using the getBBox for the measurement,
>
> Its also easy to use this to implement a way to do automatic line breaks in SVG (and with a minor change you can implement a String.height() function as well.  I use this for creating legends in the top right corner of my graphs.
>
> Bob
>
> ________________________________________
> From: d3...@googlegroups.com [d3...@googlegroups.com] on behalf of Mike Bostock [mbost...@cs.stanford.edu]

Bixente

unread,
Aug 22, 2011, 4:48:50 PM8/22/11
to d3-js
Got it! I just needed to mix both codes

.attr("transform", function(d) { return "translate(" +
xy([-74,40.716667]) + ")"; } )
.attr("x", bbox.x )
.attr("y", bbox.y )

Bixente

Bob Monteverde

unread,
Aug 27, 2011, 3:05:28 AM8/27/11
to d3-js
You might find this useful, I just adapted my jquery string width to
use svg.

This allows you to precompute the width of any string as it would be
rendered on screen in the SVG element.

//I usually prototype directly on string in m jquery version
//String.prototype.width = function(svg, string, font, aclass) {
d3.stringWidth = function(svg, string, font, aclass) {
var f = font || '12px arial';

var text = svg.append("svg:text")
.attr('class', aclass)
.attr("x", 0)
.attr("y", 0)
.style("font", f)
.style("opacity", 0)
.text(string);

return text.node().getBBox().width;
}



On Aug 22, 4:48 pm, Bixente <vhiribar...@gmail.com> wrote:
> Got it! I just needed to mix both codes
>
> .attr("transform", function(d) { return "translate(" +
> xy([-74,40.716667]) + ")"; } )
> .attr("x",bbox.x )
> .attr("y",bbox.y )
>
> Bixente
>
> On Aug 22, 3:18 pm, Bixente <vhiribar...@gmail.com> wrote:
>
>
>
>
>
>
>
> > Thanks guys for your answer. I really appreciate it. One last thing if
> > you have got time. I have managed to implement getBBox with Mike's
> > method on a map but my box is not positioned correctly on my text.
> > More precisely, the upper right corner of my box is positioned on the
> > middle of my text. I don't know how to position the centre of the box
> > on the centre of my text... (if that makes sense)
>
> > See my code for NYC:
>
> > var text = svg.append("svg:text")
> > .attr("transform", function(d) { return "translate(" +
> > xy([-74,40.716667]) + ")"; } )
> >     .attr("dy", ".35em")
> >     .attr("text-anchor", "middle")
> >     .style("font", "300 24px Helvetica Neue")
> >     .text("New York!");
>
> > varbbox= text.node().getBBox();
Reply all
Reply to author
Forward
0 new messages