我正在尝试定义一种scale content=<factor>
应用于 TikZ 图片中的节点对象的样式。其目的是缩放节点的内容而不改变节点的外部尺寸。我使用以下定义取得了相对较好的进展:
% Key to scale the content of a node by a factor #1
\tikzset{scale content/.style={
execute at begin node={
\numdef{\scale@content@nest}{\scale@content@nest+1} % increase nesting counter
\ifnumequal{\scale@content@nest}{1}{ % do not nest
\pgfmathsetmacro{\scale@content}{#1}
\begin{lrbox}{\@tempboxa}
\ifx\tikz@text@width\pgfutil@empty\else
% if 'text width' has been specified it must been scaled reciprocally
% we achieve this by typesetting in a accordingly dimensioned minipage
\pgfmathsetlength{\@tempdima}{\tikz@text@width/#1}
\begin{minipage}{\@tempdima}
\fi
}{}
},
execute at end node={
\ifnumequal{\scale@content@nest}{1}{
\ifx\tikz@text@width\pgfutil@empty\else
\end{minipage}
\fi
\end{lrbox}
\scalebox{\scale@content}{\usebox\@tempboxa}
}{}
\numdef{\scale@content@nest}{\scale@content@nest-1} % decrease nesting counter
}
}}
这很有效,除非我指定text width
取决于\textwidth
如下面的第三个示例(完整的 MWE)所示:
\documentclass{article}
\usepackage{tikz,etoolbox}
\makeatletter
% Key to scale the content of a node by a factor #1
\tikzset{scale content/.style={
execute at begin node={
\numdef{\scale@content@nest}{\scale@content@nest+1} % increase nesting counter
\ifnumequal{\scale@content@nest}{1}{ % do not nest
\pgfmathsetmacro{\scale@content}{#1}
\begin{lrbox}{\@tempboxa}
\ifx\tikz@text@width\pgfutil@empty\else
% if 'text width' has been specified, scale it accordingly by using a minipage
\pgfmathsetlength{\@tempdima}{\tikz@text@width/#1}
\begin{minipage}{\@tempdima}
\fi
}{}
},
execute at end node={
\ifnumequal{\scale@content@nest}{1}{
\ifx\tikz@text@width\pgfutil@empty\else
\end{minipage}
\fi
\end{lrbox}
\scalebox{\scale@content}{\usebox\@tempboxa}
}{}
\numdef{\scale@content@nest}{\scale@content@nest-1} % decrease nesting counter
}
}}
\makeatother
\begin{document}
\tikzset{every node/.style={draw, fill=yellow!40}}
\tikz\node[text width=3cm]{Not scaled, text width is 3cm};
\par
\tikz\node[scale content=0.7, text width=3cm]{scaled by 0.7, text width is 3cm, everything is fine};
\par
\tikz\node[scale content=0.7, text width=0.5\textwidth, text=red]{scaled by 0.7, text width is 0.5\textbackslash textwidth, so why aren't we using it?};
\par
\pgfmathsetlengthmacro{\mywidth}{0.5\textwidth}
\tikz\node[scale content=0.7, text width=\mywidth]{scaled by 0.7, text width is 0.5\textbackslash textwidth, manually expanded before, so this is how it should look like};
\end{document}
显然,TikZ 不会text width
直接扩展,这将解决问题:
% original definition from tikz.code.tex:779
\tikzoption{text width}{\def\tikz@text@width{#1}}
% Alternative definition that would work
\tikzoption{text width}{\pgfmathsetlengthmacro{\tikz@text@width}{#1}}
可是,进去之后execute at begin node
才发现已经太晚了,似乎\textwidth
已经发生了某种变化。
那么如何才能获得节点的扩展值呢text width
?
或者我应该采取一条完全不同的路线?
答案1
宏\textwidth
通过 a 更改minipage
为给定的宽度。现在,如果使用, TikZ 已经使用了 aminipage
本身。解决方案是使用 new而不是 进行缩放。否则,相对于 outer 的值将被考虑两次!text width
\textwidth
\tikz@text@width
text width
\textwidth
您可以从第 3116 行开始找到相关代码tikz.code.tex
:
\ifx\tikz@text@width\pgfutil@empty%
\else%
\begingroup%
\pgfmathsetlength{\pgf@x}{\tikz@text@width}%
\pgfutil@minipage[t]{\pgf@x}\leavevmode\hbox{}%
\tikz@text@action%
\fi%
\tikz@atbegin@node%
这\pgfutil@minipage
是正常的\minipage
宏(即 ~ \begin{minipage}
)并且\tikz@atbegin@node
是插入的位置execute at begin node
。
应用于您的 MWE:
\documentclass{article}
\usepackage{tikz,etoolbox}
\makeatletter
% Key to scale the content of a node by a factor #1
\tikzset{scale content/.style={
execute at begin node={
\numdef{\scale@content@nest}{\scale@content@nest+1} % increase nesting counter
\ifnumequal{\scale@content@nest}{1}{ % do not nest
\pgfmathsetmacro{\scale@content}{#1}
\begin{lrbox}{\@tempboxa}
\ifx\tikz@text@width\pgfutil@empty\else
% if 'text width' has been specified, scale it accordingly by using a minipage
% Here `\textwidth` now represents the original text width of the node.
\pgfmathsetlength{\@tempdima}{\textwidth/\scale@content}
\begin{minipage}{\@tempdima}
\fi
}{}
},
execute at end node={
\ifnumequal{\scale@content@nest}{1}{
\ifx\tikz@text@width\pgfutil@empty\else
\end{minipage}
\fi
\end{lrbox}
\scalebox{\scale@content}{\usebox\@tempboxa}
}{}
\numdef{\scale@content@nest}{\scale@content@nest-1} % decrease nesting counter
}
}}
\makeatother
\begin{document}
\tikzset{every node/.style={draw, fill=yellow!40}}
\tikz\node[text width=3cm]{Not scaled, text width is 3cm};
\par
\tikz\node[scale content=0.7, text width=3cm]{scaled by 0.7, text width is 3cm, everything is fine};
\par
\tracingassigns=1
\tikz\node[scale content=0.7, text width=0.5\textwidth, text=red]{scaled by 0.7, text width is 0.5\textbackslash textwidth, so why aren't we using it?};
\par
\pgfmathsetlengthmacro{\mywidth}{0.5\textwidth}
\tikz\node[scale content=0.7, text width=\mywidth]{scaled by 0.7, text width is 0.5\textbackslash textwidth, manually expanded before, so this is how it should look like};
\end{document}