我的文档的不同位置有多个元素。这些元素可能是图像、TikZ 绘图等。我想为每个元素设置最大宽度。重要的是,我还希望元素按相同的比例缩放,以便保留它们的相对大小。这个比例应该是最大的,这样所有元素都不会超过为其指定的宽度。
我知道我可以使用 将元素缩放到特定宽度\resizebox{!}{<width>}{<element>}
。但是,这会根据其自己的缩放因子单独缩放每个元素。相反,我想按相同的缩放因子缩放组内的所有元素,该缩放因子自动计算为各个缩放因子的最小值。结果应如下所示:
\begin{figure}[t]
\centering
\resizetogether{mygroup1}{0.3\textwidth}{
\includegraphics{example-image-a}
}
\caption{Image}
\end{figure}
# ...
\resizetogether{mygroup1}{0.2\textwidth}{
\includegraphics{example-image-b}
}
# ...
\resizetogether{mygroup1}{12em}{
\begin{tikzpicture}
\draw[orange, ultra thick] (4,0) -- (6,0) -- (5.7,2) -- cycle;
\end{tikzpicture}
}
这个假想的命令\resizetogether{<group>}{<width>}{<element>}
必须:
- 测量传递的宽度
<element>
。 - 计算初步缩放因子,即指定值
<width>
除以元素的宽度。 - 等到文档结束,再进行
\resizetogether
具有相同内容的其他调用<group>
。 - 按同一组中所有初步因素中最小的一个来缩放其元素。
- 将缩放的元素插入到文档中。
在 LaTeX 中怎样实现这一点?
答案1
以下最小示例提供了\setscalefactor{<len>}{<csv list of objects>}
定义一个宏\scalefactor
,其中包含使每个对象适合宽度为的最小缩放因子<len>
。使用以下方法可以实现列表处理etoolbox
和\docsvlist
。\do
可扩展长度/f
浮动p
点计算使用xfp
。
另外,\includegraphics
在本地更新以将scale
键值更新为默认的\scalefactor
after \setscalefactor
。这样,您就可以在明确指定的情况下按原样包含图像scale = \scalefactor
。
\documentclass{article}
\usepackage{graphicx,subcaption,xfp,etoolbox,letltxmacro}
\makeatletter
\newcommand{\setscalefactor}[2]{%
\def\scalefactor{9999}% Default (large) scale factor
\renewcommand*{\do}[1]{% How each element will be processed
\settowidth{\@tempdima}{##1}% Store width of element
\ifdim\scalefactor pt > \fpeval{(#1) / \@tempdima} pt
\xdef\scalefactor{\fpeval{(#1) / \@tempdima}}% Update scaling factor
\fi
}%
\docsvlist{#2}% Process list of elements
% Change the default scale factor for \includegraphics
\LetLtxMacro\oldincludegraphics\includegraphics
\renewcommand{\includegraphics}[2][]{%
\oldincludegraphics[scale = \scalefactor, ##1]{##2}%
}
}
\makeatother
\begin{document}
\begin{figure}
% Identify the scale factor to fit content within 0.4\linewidth
\setscalefactor{0.4\linewidth}{%
\includegraphics{example-image}, % First image
\includegraphics{example-image-a4-landscape} % Second image
}
\subcaptionbox{}[0.4\linewidth]{%
\includegraphics{example-image}%
}\hfill%
\subcaptionbox{}[0.4\linewidth]{%
\includegraphics{example-image-a4-landscape}%
}%
\caption{A figure caption}
\end{figure}
\end{document}
子浮点数的设置方法是subcaption
的\subcaptionbox
。
对于不同的设置和语法,使用
\resizetogether{<group>}{<width>}{<stuff>}
以下代码就足够了:
\documentclass{article}
\usepackage{graphicx,subcaption,xfp,tikz}
\makeatletter
\newcommand{\resizetogether}[3]{%
\settowidth{\@tempdimc}{#3}% Store the width of #3
\immediate\write\@auxout{%
\string\setminscalefactor{#1}{\fpeval{(#2) / (\@tempdimc)}}%
}%
\ifcsname #1@minscalefactor\endcsname
\else
\expandafter\def\csname #1@minscalefactor\endcsname{#2}%
\fi
\expandafter\scalebox\expandafter{\csname #1@minscalefactor\endcsname}{#3}%
}
\newcommand{\setminscalefactor}[2]{%
\ifcsname #1@minscalefactor\endcsname
\expandafter\expandafter\expandafter\ifdim\csname #1@minscalefactor\endcsname pt>#2 pt
\expandafter\gdef\csname #1@minscalefactor\endcsname{#2}%
\fi
\else
\expandafter\gdef\csname #1@minscalefactor\endcsname{#2}%
\fi
}
\makeatother
\begin{document}
\begin{figure}
\subcaptionbox{}[0.3\linewidth]{%
\resizetogether{mygroup1}{\linewidth}
{\includegraphics{example-image}}%
}\hfill%
\subcaptionbox{}[0.3\linewidth]{%
\resizetogether{mygroup1}{\linewidth}
{\includegraphics{example-image-a4-landscape}}%
}\hfill
\subcaptionbox{}[0.3\linewidth]{%
\resizetogether{mygroup1}{\linewidth}
{\begin{tikzpicture}
\draw[orange, ultra thick] (4,0) -- (6,0) -- (5.7,2) -- cycle;
\end{tikzpicture}}%
}
\caption{A figure caption}
\end{figure}
\end{document}
.aux
与上述最小示例相关的文件如下所示:
\relax
\setminscalefactor{mygroup1}{0.3222332023696596}
\setminscalefactor{mygroup1}{0.1224799241153155}
\setminscalefactor{mygroup1}{1.769082649490795}
\@writefile{lof}{\contentsline {figure}{\numberline {1}{\ignorespaces A figure caption\relax }}{1}}
这个想法遵循以下原则eqparbox
其中,每个元素的缩放因子都写入.aux
。当.aux
读入 时\AtBeginDocument
(默认情况下),\setminscalefactor{<group>}{<factor>}
确定同一 内所有元素的最小缩放比例<group>
,定义一个名为 的宏\<group>@minscalefactor
。如果此宏存在,则用它来缩放<stuff>
。
eqparbox
<stuff>
当内容发生更改时会发出警告。我的代码没有,因此对于 中的任何更改,您至少需要编译两次<group>
。