获取 subcaption 包中的 subfigure 和 subcaptionbox 的行为

获取 subcaption 包中的 subfigure 和 subcaptionbox 的行为

subcaption包中,创建子图的默认方式是当环境subfigure

\documentclass{article}
\usepackage{caption}
\usepackage{subcaption}
\begin{document}
\begin{figure}
 \centering
 \begin{subfigure}{0.4\textwidth}
  \centering
  Subfigure1 is located here
  \caption{Subfigure1 caption}
  \label{subfig:1}
 \end{subfigure}
 \begin{subfigure}{0.4\textwidth}
  \centering
  Subfigure2 is located here
  \caption{Subfigure2 caption}
  \label{subfig:2}
 \end{subfigure}
 \caption{Figure caption}
 \label{fig}
\end{figure}
\end{document}

我喜欢这种语法,尤其是图形在前,然后是标题,然后是标题的标签。但是,我不喜欢\textwidth在环境中指定。我更希望这个参数是可选的,默认值是图形的宽度。

解决此问题的一个方法是使用保存盒,但图形的来源会(稍微)偏离其主要使用位置。

subcaption软件包通过以下命令提供了该问题的解决方案\subcaptionbox

\documentclass{article}
\usepackage{caption}
\usepackage{subcaption}
\begin{document}
\begin{figure}
 \centering
 \subcaptionbox{Subfigure1 caption\label{subfig:1}}{
  \centering
  Subfigure1 is located here}
 \subcaptionbox{Subfigure2 caption\label{subfig:2}}{
  \centering
  Subfigure2 is located here}
 \caption{Figure caption}
 \label{fig}
\end{figure}
\end{document}

现在指定\textwidth是可选的,默认为图形的宽度,但源代码的可读性要差得多。我不喜欢这个解决方案,原因如下:

  1. 将大量代码放在 中会更容易编写、阅读和理解\begin{}...\end{}\someCommand{...}(很容易使用错误数量的花括号。)
  2. 图形、标题和标签的写法与它们的排版顺序(默认)不符,而这是我所认为的顺序。
  3. 放置标题的位置并不明确。(它只是放置\subcaptionbox在某些{}'s 之间的必需值,因此如果标题当前为空白,则不知道此语法的合著者将不知道如何添加标题。)

问题:

有没有办法两全其美?如何才能获得与使用环境等效的行为subfigure,但同时又具有可选的规范\textwidth(并默认为图形的宽度)?

(这个问题是关于subcaption包的,因为这似乎是子图的最佳包。我愿意接受建议,另一个包更好并且满足我的要求。)

答案1

这不支持所有功能:无法表达可选\subcaptionbox参数。<inner-pos>

环境的可选参数xsubcaption是子图的明确宽度。

\documentclass{article}
\usepackage{caption}
\usepackage{subcaption}
\usepackage{environ}

\makeatletter
\environfinalcode{}
\NewEnviron{xsubcaption}[1][-1sp]
 {\let\xsc@theoptcaption\@empty
  \let\xsc@thecaption\@empty
  \let\xsc@thelabel\@empty
  \expandafter\xsc@checkcaption\BODY\caption\xsc@checkcaption
  \expandafter\xsc@checklabel\BODY\label\xsc@checklabel
  \begingroup\edef\x{\endgroup
    \noexpand\subcaptionbox
      \ifx\xsc@theoptcaption\@empty\else
        [\unexpanded\expandafter{\xsc@theoptcaption}]%
      \fi
      {\unexpanded\expandafter{\xsc@thecaption}%
       \ifx\xsc@thelabel\@empty\else
         \noexpand\label{\unexpanded\expandafter{\xsc@thelabel}}%
       \fi} 
      \ifdim#1=-1sp % no optional argument
      \else
        [#1]%
      \fi
      {\unexpanded{\renewcommand\caption[2][]{}\renewcommand{\label}[1]{}}%
       \unexpanded\expandafter{\BODY}}}\x
}

\long\def\xsc@checkcaption#1\caption#2\xsc@checkcaption{%
  \if\relax\detokenize{#2}\relax
    \expandafter\@gobble
  \else
    \expandafter\@firstofone
  \fi
  {\expandafter\xsc@getcaption\BODY\xsc@getcaption}%
}
\long\def\xsc@getcaption#1\caption#2#3\xsc@getcaption{%
  \if[\detokenize{#2}%
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
  {\expandafter\xsc@getcaptionopt\BODY\xsc@getcaptionopt}%
  {\def\xsc@thecaption{#2}}%
}
\long\def\xsc@getcaptionopt#1\caption[#2]#3#4\xsc@getcaptionopt{%
  \def\xsc@theoptcaption{#2}%
  \def\xsc@thecaption{#3}%
}
\long\def\xsc@checklabel#1\label#2\xsc@checklabel{%
  \if\relax\detokenize{#2}\relax
    \expandafter\@gobble
  \else
    \expandafter\@firstofone
  \fi
  {\expandafter\xsc@getlabel\BODY\xsc@getlabel}%
}
\long\def\xsc@getlabel#1\label#2#3\xsc@getlabel{%
  \def\xsc@thelabel{#2}%
}
\makeatother

\begin{document}
\begin{figure}
\centering
\begin{xsubcaption}
\centering
Subfigure1 is located here
\caption{Subfigure1 caption}\label{subfig:1}
\end{xsubcaption}
\begin{xsubcaption}
\centering
Subfigure2 is located here
\end{xsubcaption}
\begin{xsubcaption}[3cm]
\centering
Subfigure3 is located here
\caption[A]{BBB}
\end{xsubcaption}
\caption{Figure caption}
\label{fig}
\end{figure}

\ref{subfig:1} \ref{fig}
\end{document}

在此处输入图片描述

我使用environ包将环境的主体收集到宏中\BODY。然后我检查\caption主体中是否出现;如果出现,我检查它是否有可选参数。标题(以及“列表标题”,​​如果存在)存储在宏中,然后\subcaptionbox从各个部分构建整个指令(当主体排版时,\caption被重新定义为不执行任何操作)。

(添加)执行相同的检查来捕获\label参数之外的命令\caption(当然,两种方式都支持)。

最后,\subcaptionbox执行使用上述代码确定的所有参数的宏。它看起来很复杂,但实际上并不难:这是在标记列表中捕获某个标记(\caption\label)存在的标准方法,在本例中是环境的内容,可作为的扩展使用\BODY

相关内容