在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
是可选的,默认为图形的宽度,但源代码的可读性要差得多。我不喜欢这个解决方案,原因如下:
- 将大量代码放在 中会更容易编写、阅读和理解
\begin{}...\end{}
。\someCommand{...}
(很容易使用错误数量的花括号。) - 图形、标题和标签的写法与它们的排版顺序(默认)不符,而这是我所认为的顺序。
- 放置标题的位置并不明确。(它只是放置
\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
。