如何将多个元素缩放到最大宽度,同时保持它们的相对大小固定?

如何将多个元素缩放到最大宽度,同时保持它们的相对大小固定?

我的文档的不同位置有多个元素。这些元素可能是图像、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>}必须:

  1. 测量传递的宽度<element>
  2. 计算初步缩放因子,即指定值<width>除以元素的宽度。
  3. 等到文档结束,再进行\resizetogether具有相同内容的其他调用<group>
  4. 按同一组中所有初步因素中最小的一个来缩放其元素。
  5. 将缩放的元素插入到文档中。

在 LaTeX 中怎样实现这一点?

答案1

以下最小示例提供了\setscalefactor{<len>}{<csv list of objects>}定义一个宏\scalefactor,其中包含使每个对象适合宽度为的最小缩放因子<len>。使用以下方法可以实现列表处理etoolbox\docsvlist\do可扩展长度/f浮动p点计算使用xfp

另外,\includegraphics在本地更新以将scale键值更新为默认的\scalefactorafter \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>

相关内容