tikz:一个固定宽度的大盒子,里面有较小的盒子

tikz:一个固定宽度的大盒子,里面有较小的盒子

我想用 tikz 渲染类似的东西:

盒子

周围的大框应该表现得像一个小页面:宽度是固定的,如果我们在里面添加足够小的框,高度应该会增加。目前,我使用以下(简化的)MWE 来产生:

\begin{tikzpicture}
\tikzstyle{bigbox} = [minimum height=2cm,draw,rounded corners, rectangle]
\tikzstyle{box} = [minimum height=0.8cm,draw,rounded corners, draw,rectangle]
\node[bigbox](outbox)%
{
    \begin{minipage}{3cm}
        \tikz{\node[box]{12};}
        \tikz{\node[box]{12};}
        \tikz{\node[box]{12};}
        \tikz{\node[box]{12};}
    \end{minipage}
};
\end{tikzpicture}

正如你所注意到的,我将 嵌套\tikz在 里面tikzpicture,这很糟糕,因为我刚刚在这篇帖子来自 Andrew Stacey。他建议使用中的“适合”选项\usetikzlibrary{fit},但在这种情况下我不知道该怎么做。

答案1

Mark 已经回答了关于在内部内容到位后对外部矩形进行排序的问题(考虑到约束条件,fitlayer方法似乎更合适)。我要解决的问题是让内部框使用“换行”功能自行定位。这不是一个完整的解决方案,但如果它看起来是正确的,那么我认为剩下的事情并不难做(但我想在做之前先检查一下)。

我对这个问题的评论(引用自真实的意大利工作 (Italian Job) 的思路是对的,但还不够。该positioning库可以接受相当复杂的表达式 - 可以做类似的事情above={(\x > \y ? 3cm : -2cm)} of a.south- 但事实证明,这些都是计算出来的节点布局完毕,所有复杂的定位工作都由节点代码完成,而不是定位代码完成。

因此,我们必须将节点代码用于我们的邪恶目的。幸运的是,这相对容易(如果全部执行起来有点乏味)。节点通过指定锚点来定位。该锚点位于(0,0)(定位库或只是 TikZ,设置了节点所在的(0,0)位置)。因此,如果我们想将节点放置在稍微不同的地方,我们只需定义一个相当复杂的锚点。这需要定义一个新形状或使用 Martin Scharrer 的代码将新锚点添加到现有形状。我选择了前者,并定义了一个“可移动矩形”。这个矩形具有其north west锚点可以依赖于参数的属性。嗯,实际上需要一点计算。这个计算使用有关节点大小的信息,因为它是在布局节点时计算的。我的计算是:

\pgfmathparse{(\mrwidth > 1cm ? "(a.north east)" : "(a.south west)")}
\let\mrvector=\pgfmathresult

这将测试一个宏,\mrwidth该宏恰好设置为节点的宽度(mr=“可移动矩形”)(显然,可以对其进行调整以使高度也可用)。如果宽度很大,则返回(a.north east),如果很小,则返回(a.south west)。结果保存为\mrvector。此代码在节点计算north west矩形的锚点时执行,锚点会根据结果进行移动。由于节点坐标是“绝对的”,因此结果是当前节点的西北锚点位于节点的东北或西南,a具体取决于其宽度。如果坐标是这样的(0,2cm),这将表示一个相对的调整。

因此,我们的想法是进行一个稍微复杂一点的测试,看看节点的宽度是否会超出给定的宽度,如果是,则将节点锚定在下一行。这需要多做一点工作,但不会太多,因为通常会有多个节点参与计算。但这只是记账。

我将把完整代码放在这个答案的末尾。如果全部打包在一个漂亮的包中,语法将类似于:

\begin{document}
\begin{tikzpicture}
\node[box] (a) {A};
\node[box,moveable rectangle,anchor=north west,moveable] at (a.south east) (b) {B};
\node[box,moveable rectangle,anchor=north west,moveable] at (a.south east) (c) {ABCDEFG};
\end{tikzpicture}
\end{document}

结果:

tikz 可流动节点

如您所见,两个节点的规格完全相同,但一个节点位于a节点旁边,另一个位于节点下方。

这是目前为止的代码。我目前只修改了锚点north west。显然,其他的也需要修改。压力测试和我所做的一些假设可能会被证明是完全荒谬的……

\documentclass{article}
%\url{http://tex.stackexchange.com/q/40234/86}
\usepackage{tikz}
\makeatletter
\tikzset{
  box/.style={
    minimum height=0.8cm,
    draw,
    rounded corners,
    rectangle
  },
  moveable rectangle/condition/.code={%
    \pgfmathparse{(\mrwidth > 1cm ? "(a.north east)" : "(a.south west)")}
    \let\mrvector=\pgfmathresult
  },
  moveable/.is if=mr@moveable,
}
\def\mrvector{(0,0)}
\newif\ifmr@moveable
\pgfdeclareshape{moveable rectangle}{%
  \inheritsavedanchors[from=rectangle]%
  \anchor{north west}{%
    \ifmr@moveable
    \northeast
    \pgf@xa=\pgf@x
    \southwest
    \advance\pgf@xa by -\pgf@x
    \edef\mrwidth{\the\pgf@xa}%
    \pgfkeys{/tikz/moveable rectangle/condition}%
    \tikz@scan@one@point\pgfutil@firstofone\mrvector
    \pgf@xa=-\pgf@x
    \pgf@ya=-\pgf@y
    \northeast
    \advance\pgf@ya by \pgf@y
    \southwest
    \advance\pgf@xa by \pgf@x
    \pgf@x=\pgf@xa
    \pgf@y=\pgf@ya
    \else
    \northeast
    \pgf@ya=\pgf@y
    \southwest
    \pgf@y=\pgf@ya
    \fi
  }
  \inheritbackgroundpath[from=rectangle]
}
\makeatother
\begin{document}
\begin{tikzpicture}
\node[box] (a) {A};
\node[box,moveable rectangle,anchor=north west,moveable] at (a.south east) (b) {B};
\node[box,moveable rectangle,anchor=north west,moveable] at (a.south east) (c) {ABCDEFG};
\end{tikzpicture}
\end{document}

答案2

以下内容比较粗略,也许使用矩阵会更好,但它是为了演示如何在背景中使用拟合框。

\documentclass[10pt]{article}
\usepackage{tikz}
\usetikzlibrary{backgrounds,fit}

\begin{document}

\begin{tikzpicture}[outer sep=0.05cm,node distance=0.8cm,]
\tikzstyle{bigbox} = [draw=blue!50, thick, fill=blue!10, rounded corners, rectangle]
\tikzstyle{box} = [minimum size=0.6cm, rounded corners,rectangle, fill=blue!50]
%
\node[box] (11) {1};
\node[box,right of=11] (12) {2};
\node[box,right of=12] (13) {3};
\node[box,below of=11] (21) {4};
\node[box,right of=21] (22) {5};
\node[box,right of=22] (23) {6};
%
\begin{pgfonlayer}{background}
  \node[bigbox] [fit = (11) (23)] {};
\end{pgfonlayer}
%
\end{tikzpicture}

\end{document}

请注意,确保fit = (11) (22)框包含左上角和右下角的框。对于更复杂的图表,您可以添加更多节点名称以适应。

在此处输入图片描述

使用 TikZ 可以更干净地获得类似的结果matrix。另一个好处是不需要拟合,因为矩阵本身就采用了这种bigbox风格。

\begin{tikzpicture}
\tikzstyle{bigbox} = [draw=blue!50, thick, fill=blue!10, rounded corners, rectangle]
\tikzstyle{box} = [minimum size=0.6cm, rounded corners,rectangle, fill=blue!50]
%
\matrix[row sep=2mm, column sep=2mm, inner sep=2mm, bigbox, every node/.style=box] {
\node {1}; & \node {2}; & \node {3};\\
\node {4}; & \node {5}; & \node {6};\\
};
%
\end{tikzpicture}

matrix正如 percusse 所指出的,通过添加库可以进一步简化这一过程

\usetikzlibrary{matrix}

并使用matrix of nodes矩阵的选项。

\begin{tikzpicture}
\tikzstyle{bigbox} = [draw=blue!50, thick, fill=blue!10, rounded corners, rectangle]
\tikzstyle{box} = [minimum size=0.6cm, rounded corners,rectangle, fill=blue!50]
%
\matrix[row sep=2mm, column sep=2mm, inner sep=2mm, bigbox, matrix of nodes, every node/.style=box] {
1 & 2 & 3\\
4 & 5 & 6\\
};
%
\end{tikzpicture}

相关内容