我正在开发一个广泛使用命令来pgfkeys
生成 tikz 图片的软件包。下面是一个简单的示例:
\documentclass[tikz,border=5pt]{standalone}
\makeatletter
\usetikzlibrary{shapes.geometric, calc}
\newcommand{\example}[2][]{
\tikzset{
/Example/.cd,
caption/.store in=\Example@caption,
caption=X,
#1,
}
\draw [local bounding box=M] rectangle (1,1);
\node at (0.5,0.5) {\Example@caption};
}
\makeatother
\begin{document}
\begin{tikzpicture}
\example[caption=A];
\end{tikzpicture}
\end{document}
正如预期的那样,这将产生以下输出:
(请记住,这是一个为了简化而举的例子,并不反映真实命令的复杂性,真实命令包含更多可以执行更复杂操作的键)。
我想要创建两个新的列表环境,我可以使用不同的键值多次向其中添加命令之一。然后使用 tikz 绘制的括号将生成的图片“分组”,或使用从命令内定义的局部边界框的西南角向下延伸一定长度的线“堆叠”,以便它与下一张图片(如果存在)连接(所有图片的间距均相等,并且每张图片的整体尺寸相同):
我理想中寻找的是类似于这样的列表环境结构:
\begin{examplestack}
\item \example[caption=A]
\item \example[caption=B]
\item \example[caption=C]
\end{examplestack}
\begin{examplegroup}
\item \example[caption=A]
\item \example[caption=B]
\item \example[caption=C]
\end{examplegroup}
堆栈和组都应在tikzpicture
画布内有原点偏移,组位于括号的顶端,堆栈位于最后一行的底部(“旗杆”的底部)。这样,如果将它们叠加在另一个图层(如地图)上,它们就可以正确放置。
答案1
概念验证。至少对于这个简单案例来说,这种方法似乎有效。长度需要时不时调整,例如,每个项目的垂直偏移量只是硬编码为 1.2 厘米。总的来说,这不是一种非常灵活的方法,我相信其他人可以做得更好。
\documentclass[tikz,border=5pt]{standalone}
\makeatletter
\usetikzlibrary{shapes.geometric, calc}
\newcommand{\example}[2][]{
\tikzset{
/Example/.cd,
caption/.store in=\Example@caption,
caption=X,
#1,
}
\draw [local bounding box=M] rectangle (1,1);
\node at (0.5,0.5) {\Example@caption};
}
\makeatother
\newcounter{exitem}
\newenvironment{examplestack}{
\setcounter{exitem}{0}
\renewcommand\item{
% if you only want to draw a line between items
%\ifnum \value{exitem}>0
% \draw ([xshift=0.5\pgflinewidth]current bounding box.south west) -- ++(0,-0.2cm);
%\fi
%
% if you also want the line below the last item -- not very elegant
\draw (0,{-(1.2cm+\theexitem*1.2cm)}) -- ++(0,-2mm);
%
\stepcounter{exitem}\scoped[yshift=-\theexitem*1.2cm]}
\tikzpicture
}{
%\draw (current bounding box.north west) -- ([yshift=-3pt]current bounding box.south west);
\node [above right] at (current bounding box.north west) {``Stack''};
\endtikzpicture
}
\newenvironment{examplegroup}{
\setcounter{exitem}{0}
\renewcommand\item{\stepcounter{exitem}\scoped[yshift=-\theexitem*1.2cm]}
\tikzpicture
}{
\draw ([shift={(5pt,3pt)}]current bounding box.north west) -| ([shift={(-3pt,-3pt)}]current bounding box.south west) -- ++(8pt,0)
(current bounding box.west) -- ++(-5pt,0);
\node [above right] at (current bounding box.north west) {``Group''};
\endtikzpicture
}
\begin{document}
\begin{examplegroup}
\item\example[caption=A];
\item\example[caption=B];
\item\example[caption=C];
\end{examplegroup}
\begin{examplestack}
\item\example[caption=A];
\item\example[caption=B];
\item\example[caption=C];
\end{examplestack}
\end{document}
答案2
我觉得我应该对此添加一个答案,因为我设法想出了一个比 Torbjørn T 的答案更好、更灵活的解决方案。他们的解决方案不允许不同高度的图片之间有相同的间距。通过使用长度宏,我能够存储前一张图片的长度并使用它来偏移下一张图片,并且使用坐标集我能够将它们连接到“堆栈”中。
重要的提示:\item
已被重新定义为接受一个参数,因此在环境中,您应该使用\item{<picture>}
而不是\item <picture>
。
该解决方案使用xparse
更清晰的命令和环境语法,但可以同样轻松地使用普通的 LaTeX 解决方案。
序言(以及 MWE 的其余部分):
\newcounter{exitem}
\newlength{\itemlength}
“Stack” 语法:
\NewDocumentEnvironment{examplestack}{}{
\setlength{\itemlength}{0}
\begin{scope}
\setcounter{exitem}{0}
\RenewDocumentCommand\item{m}{
\scoped[yshift=-\itemlength, local bounding box=T]
##1;
\ifnum \value{exitem}>0
\pgfmathtruncatemacro\result{\value{exitem}-1}
\draw ($(M.south west) + (0, -0.25)$) -- (F\result);
\fi
\coordinate (F\arabic{exitem}) at (M.north west);
\pgfpointdiff{\pgfpointanchor{T}{north west}}{\pgfpointanchor{T}{south west}}
\addtolength{\itemlength}{\pgf@y-5pt} % 5pt is the spacing between pictures.
\stepcounter{exitem}}
}{\end{scope}}
“组”语法:
\NewDocumentEnvironment{examplegroup}{}{
\setlength{\itemlength}{0}
\begin{scope}[local bounding box=G]
\RenewDocumentCommand\item{m}{
\scoped[yshift=-\itemlength, local bounding box=T]
##1;
\pgfpointdiff{\pgfpointanchor{T}{north west}}{\pgfpointanchor{T}{south west}}
\addtolength{\itemlength}{\pgf@y-5pt}} % 5pt is the spacing between pictures.
}{
\draw ([shift={(5pt,3pt)}]G.north west) -| ([shift={(-3pt,-3pt)}]G.south west) -- ++(8pt,0)
(G.west) -- ++(-5pt,0);
\end{scope}}
例子:
\begin{examplegroup}
\item{\example[caption=A]}
\item{\example[caption=B]}
\item{\example[caption=C]}
\end{examplegroup}
\begin{examplestack}
\item{\example[caption=A]}
\item{\example[caption=B]}
\item{\example[caption=C]}
\end{examplestack}