I would like to be able to scale text to the width of a TikZ node.
Using \widthof within tikzpicture as a starting point, I've arrived at somewhat of a solution, except it has incorrect spacing, and can probably be done more elegantly.
\documentclass{article}
\usepackage{tikz}
\usepackage{calc}
\usepackage{xstring}
\usepackage{ifthen}
\newlength{\scaleratio}
\makeatletter
\newcommand{\settowidthofnode}[2] {%
\pgfextractx{#1}{\pgfpointanchor{#2}{east}}%
\pgfextractx{\pgf@xa}{\pgfpointanchor{#2}{west}}%
\addtolength{#1}{-\pgf@xa}%
}%
\makeatother
\makeatletter
\newcommand{\shrinktowidthofnode}[2] {%
\settowidthofnode{\pgf@xb}{#2}%
\setlength{\scaleratio} {%
{1.0pt * \ratio{\pgf@xb}{\widthof{#1}}}%
}%
\ifthenelse{\lengthtest{\scaleratio < 1.0pt}} {%
\setlength{\scaleratio}{\scaleratio}%
\tokenize{\tokenized}{\the\scaleratio}%
\StrBefore{\tokenized}{pt}[\result]%
\scalebox{\result}{#1}%
} {%
#1%
}%
}%
\makeatother
\begin{document}
\begin{tikzpicture}[every node/.style={draw,rectangle}]
\draw[step=0.5cm,gray,very thin] (-3,-3) grid (3,3);
\node (n) {blah};
\node (m) [below of=n] {\shrinktowidthofnode{AAAAAAAA}{n}};
\node (o) [below of=m] {\scalebox{0.43259}{AAAAAAAA}};
\end{tikzpicture}
\end{document}
The output looks like this:
It's hard to see, but if you zoom in, the middle node's bounding box is larger than it should be, and there's some extra space on its left (there was more extra space earlier, but for some reason adding %
to the end of each line in the \newcommand
s helped).
The bottom node is the ground truth. Any ideas?
Best Answer
The
east
andwest
anchors include the inner margin between the text and the frame (inner sep
). So you set your text as wide as the frame of the other node, not its text. Then the new node adds its own inner margin which makes it wider. I would use thetext
andcenter
anchors instead (seepgfmanual
page 420). They give you half the text width, so this must only be doubled.There is also no need to use
calc
withtikz
. It comes with its own math enginepgfmath
which is more powerful. Also note that\pgfpointanchor
(and all other\pgfpoint...
macros) already stores the x-value into\pgf@x
. The\pgfextractx
just calls\pgf@process
(which executes the\pgfpoint...
macro locally and only makes the result global available) and set#1=\pgf@x
.In your case it's better to work with
\pgf@x
directly, just keep in mind that it will be overwritten by the next\pgfpoint...
macro. Also there is no need to calculate the scale factor by yourself. Use\resizebox{<width>}{<height>}{<content>}
from thegraphics
package (already loaded bypgf
ortikz
). Use a!
for the height here so that it scales accordantly to the width.Now there seems to be an unwanted space inside either
\pgfpointanchor
or the anchor code itself which causes the extra white space before yourAAAAAAA
s. Adding\unskip
after them fixes this. But this is worth investigating and to report it to the developers.Result: