带有空白处的分层图

带有空白处的分层图

我正在尝试实现以下目标:

+---------------------+ +---------------+
|          A          | |       B       |
+---------------------+ +---------------+
                  +---------+
########1######## |    C    | #####2#####
                  +---------+
+---+ +---------+ +---------+ +---+ +---+
| D | |    E    | |    F    | | G | | H |
+---+ +---------+ +---------+ +---+ +---+
      +---+
##3## | I | ###########4########### ##5##
      +---+
+---------+ +---------------------+ +---+
|    J    | |          K          | | L |
+---------+ +---------------------+ +---+

在这里,标签应该代表空白区域。我看过这个答案,但该解决方案并不完全符合我的需要。

为了指定我的图表,我想要做的是逐行、从左到右设计它;按顺序列出我想要绘制的所有块/空白处。

为了正确重叠,我想为每个块/空白空间指定与其共享垂直空间的上一行中的哪些块。我怎么做?或者更好的是,我如何获得期望的最终结果?

如果添加一行,要求共享窄块的垂直空间,从而导致块被拉伸,那就太好了。以上面的例子为例;如果C本身很窄,让它与和共享垂直空间A会使B它变得稍微宽一些。同样,由于#4共享了部分E垂直空间,E必须变得更宽以容纳I和的一部分#4。最后,由于H#5共享L相同的垂直空间,它们应该同样宽。

也许,按照以下思路来思考这个行/列分解推特引导模型可以帮助进一步形象化这个问题。

更新(2013-12-11):
我尝试按照建议使用 TikZ 矩阵。因此我不得不查找如何实现跨列。这是使用该技术的 MWE:

\documentclass{article}
\usepackage{tikz}

\usetikzlibrary{positioning,calc,matrix,fit}

\makeatletter
\newdimen\multi@col@width
\newdimen\multi@col@margin
\newcount\multi@col@count
\multi@col@width=0pt

\tikzset{
  multicol/.code={%
    \global\multi@col@count=#1\relax
    \global\let\orig@pgfmatrixendcode=\pgfmatrixendcode
    \global\let\orig@pgfmatrixemptycode=\pgfmatrixemptycode
    \def\pgfmatrixendcode##1{\orig@pgfmatrixendcode%
      ##1%
      \pgfutil@tempdima=\pgf@picmaxx
      \global\multi@col@margin=\pgf@picminx
      \advance\pgfutil@tempdima by -\pgf@picminx
      \divide\pgfutil@tempdima by #1\relax
      \global\multi@col@width=\pgfutil@tempdima
      \pgf@picmaxx=.5\multi@col@width
      \pgf@picminx=-.5\multi@col@width
      \global\pgf@picmaxx=\pgf@picmaxx
      \global\pgf@picminx=\pgf@picminx
      \gdef\multi@adjust@position{%
        \setbox\pgf@matrix@cell=\hbox\bgroup
        \hfil\hskip-1.5\multi@col@margin
        \hfil\hskip-.5\multi@col@width
        \box\pgf@matrix@cell
        \egroup
      }%
      \gdef\multi@temp{\aftergroup\multi@adjust@position}%
      \aftergroup\multi@temp
    }
    \gdef\pgfmatrixemptycode{%
      \orig@pgfmatrixemptycode
      \global\advance\multi@col@count by -1\relax
      \global\pgf@picmaxx=.5\multi@col@width
      \global\pgf@picminx=-.5\multi@col@width
      \ifnum\multi@col@count=1\relax
       \global\let\pgfmatrixemptycode=\orig@pgfmatrixemptycode
      \fi
    }
  }
}
\makeatother

\begin{document}
\begin{tikzpicture}{
\matrix[matrix of nodes, nodes={draw}, draw=black] (Layers) {
    %row 1
    |[multicol=4]| A &&&&|[multicol=3]| B && \\
    %row 2
    |[multicol=3]| &&&|[multicol=2]| C &&|[multicol=2]| & \\
    %row 3
    D &|[multicol=2]| E &&|[multicol=2]| F && G & H \\
    %row 4
    & I &|[multicol=4]| &&& \\
    %row 5
    |[multicol=2]| J &&|[multicol=4]| K &&&& L \\
};
}
\end{tikzpicture}
\end{document}

然而,结果有些不令人满意(不需要的方框出现在一些空格和字母周围的方框不够宽):
渲染

尽管目前取得的结果并不令人满意,但我还是尝试将其改编成更具视觉吸引力的版本(只需替换\begin{tikzpicture}...\end{tikzpicture}MWE 中的部分):

\begin{tikzpicture}[
base/.style={
    rounded corners,
    font={\sffamily\bfseries},
    align=center,
},
block/.style={
    base,
    draw=lime,
    fill=blue,
    font={\sffamily\bfseries\color{white}},
},]{
\matrix[draw=black] (Layers) {
    %row 1
    |[multicol=4]|
        \node[block] (a) {A};
    &&&&|[multicol=3]|
        \node[block] (b) {B};   
    && \\
    %row 2
    |[multicol=3]| &&&|[multicol=2]|
        \node[block] (c) {C};   
    &&|[multicol=2]| & \\
    %row 3
        \node[block] (d) {D};
    &|[multicol=2]|
        \node[block] (e) {E};   
    &&|[multicol=2]|
        \node[block] (f) {F};   
    &&
        \node[block] (g) {G};   
    &
        \node[block] (h) {H};
    \\
    %row 4
    &
        \node[block] (i) {I};   
    &|[multicol=4]| &&& \\
    %row 5
    |[multicol=2]|
        \node[block] (j) {J};   
    &&|[multicol=4]|
        \node[block] (k) {K};   
    &&&&
        \node[block] (l) {L};   
    \\
};
}
\end{tikzpicture}

结果如下:
渲染

很明显,大多数盒子都没有正确拉伸到预期尺寸。我该如何解决这个问题?

答案1

我以 12 厘米的块和 4 毫米的松动为基础,然后对块进行调整,以使事物更好地排列。

\documentclass{article}

\newlength{\cellH}% cell height
\setlength{\cellH}{.8cm}

\newlength{\cellW}% cell width (1 unit)
\setlength{\cellW}{.8cm}

\newlength{\cellM}% (cell height - character height)/2
\settoheight{\cellM}{ABCDEFGHIJKL12345}
\addtolength{\cellM}{-\cellH}
\setlength{\cellM}{-0.5\cellM}

\newcommand{\cell}[2]% #1 = width, #2 = text
{\framebox[#1\cellW][c]{\raisebox{\cellM}[\cellH]{#2}}}

\newcommand{\blank}[2]% #1 = width, #2 = text
{\makebox[#1\cellW][c]{\raisebox{\cellM}[\cellH]{#2}}}

\begin{document}

\centering{\parbox{12.4\cellW}{%
\cell{7.65}{A} \cell{4.65}{B}
\blank{6}{1} \cell{3}{C} \blank{3}{2}
\cell{2}{D} \cell{3}{E} \cell{3}{F} \cell{2}{G} \cell{2}{H}
\blank{2}{3} \cell{2}{I} \blank{6.1}{4} \blank{2}{5}
\cell{4.1}{J} \cell{6.1}{K} \cell{2}{L}
\rule{12\cellW}{0pt}% right justify last line (I miss \hshrink)
}}

\结束{文档}

盒装版本

这是使用 Tikz 的版本。使用“右上方”将 (x,y) 位置放在左下角,而不是中心。

\documentclass{article}
\usepackage{tikz}

\newlength{\cellH}% cell height
\setlength{\cellH}{.8cm}

\newlength{\cellW}% cell width (1 unit)
\setlength{\cellW}{.8cm}

\newcommand{\cell}[3]% #1 = border, #2 = width, #3 = text
{node[draw=#1,minimum width=#2\cellW]{#3}}

\pgfsetxvec{\pgfpoint{\cellW}{0cm}}% x coordinate
\pgfsetyvec{\pgfpoint{0cm}{\cellH}}% y coordinate

\begin{document}
\begin{center}
\begin{tikzpicture}
\path[every node/.style={minimum height=\cellH, above right}]
 (0,4.4) \cell{black}{7.65}{A}
 (7.75,4.4) \cell{black}{4.65}{B}
 (0,3.3) \cell{white}{6}{1}
 (6.2,3.3) \cell{black}{3}{C}
 (9.4,3.3) \cell{white}{3}{2}
 (0,2.2) \cell{black}{2}{D}
 (2.1,2.2) \cell{black}{3}{E}
 (5.2,2.2) \cell{black}{3}{F}
 (8.3,2.2) \cell{black}{2}{G}
 (10.4,2.2) \cell{black}{2}{H}
 (0,1.1) \cell{white}{2}{3}
 (2.1,1.1) \cell{black}{2}{I}
 (4.2,1.1) \cell{white}{6.1}{4}
 (10.4,1.1) \cell{white}{2}{5}
 (0,0) \cell{black}{4.1}{J}
 (4.2,0) \cell{black}{6.1}{K}
 (10.4,0) \cell{black}{2}{L};
\end{tikzpicture}
\end{center}
\end{document}

tikz 版本

答案2

我不是 100% 满意@John Kormylo回答,所以我继续寻找解决方案。
这个答案经过@Qrrbrbirlbel参考名为“node-families”的 TikZ 库(下载这里) 为样式\nodes 引入了新的键:特别Minimum Width=someAlias是确保具有该属性的所有节点都具有相同的最小宽度(并且如果其他样式选项相同,则实际上具有相同的总宽度)。

这是我的解决方案(MWE):

\documentclass{article}
\usepackage{tikz}

\usetikzlibrary{positioning,node-families,calc,matrix,fit}

\begin{document}
\begin{center}
\begin{tikzpicture}[node distance=3pt,
base/.style={
    rounded corners,
    font={\sffamily\bfseries},
    align=center,
},
block/.style={
    base,
    draw=black,
    fill=orange,
    font={\small\sffamily\bfseries\color{white}},
    inner sep=3pt,
},
overlap/.style={
    minimum width=1.5em,
    %draw=red, %enable to aid during construction
},
group/.style={
    inner sep=0,
    %draw=black, %enable to aid during construction
},]{
{%row3
    \node[block, Minimum Height=row3] (d) {D};
    \node[block, right=of d, Minimum Height=row3, Minimum Width=e_iIOverlapRGroup] (e) {E};
    \node[block, right=of e, Minimum Height=row3, Minimum Width=cOverlapGroup_c_f] (f) {F};
    \node[block, right=of f, Minimum Height=row3] (g) {G};
    \node[block, right=of g, Minimum Height=row3, Minimum Width=h_l] (h) {H};
}
{%row2
    \node[block, above=of f, Minimum Height=row2, Minimum Width=cOverlapGroup_c_f] (c) {C};
}
{%row1
    %helper nodes
    \node[overlay, above=of c.north west, anchor=south west, Minimum Height=row1] (cOverlapL) {};
    \node[overlay, right=of cOverlapL, Minimum Height=row1] (cOverlapR) {};
    \node[group, fit=(cOverlapL)(cOverlapR), above=of c, Minimum Height=row1, Minimum Width=cOverlapGroup_c_f] (cOverlapGroup) {};
    %block nodes
    \node[block, left=of cOverlapGroup.center, xshift=1.5pt, Minimum Height=row1, Minimum Width=a_aDGroup] (a) {A};
    \node[block, right=of a, Minimum Height=row1, Minimum Width=b_bAGroup] (b) {B};
    %more helper nodes
    \node[group, fit=(a)(d), Minimum Width=a_aDGroup] (aDGroup) {};
    \node[group, fit=(b)(h), Minimum Width=b_bAGroup] (bHGroup) {};
}
{%row4
    %block nodes
    \node[block, below=of e.south west, anchor=north west, Minimum Height=row4] (i) {I};
    %helper nodes
    \node[overlap, right=of i, Minimum Height=row4] (iOverlapR) {};
    \node[group, fit=(i)(iOverlapR), below=of e, Minimum Height=row4, Minimum Width=e_iIOverlapRGroup] (iIOverlapRGroup) {};
    \node[group, fit=(d)(i), Minimum Width=dIGroup_j] (dIGroup) {};
    \node[group, fit=(iOverlapR)(g), Minimum Width=iOverlapRGGroup_k] (iOverlapRGGroup) {};
}
{%row5
    \node[block, below=of dIGroup, Minimum Height=row5, Minimum Width=dIGroup_j] (j) {J};
    \node[block, right=of j, Minimum Height=row5, Minimum Width=iOverlapRGGroup_k] (k) {K};
    \node[block, right=of k, Minimum Height=row5, Minimum Width=h_l] (l) {L};
}
}
\end{tikzpicture}
\end{center}
\end{document}

不过,正如@Qrrbrbirlbel 所描述的那样,使用这些属性需要您编译文档几次。对我来说,这不是问题,因为我的文档无论如何都必须编译几次才能正确获取所有(交叉)引用、附录等。
下面,您可以看到我的示例正确运行所需的三次运行:

第 1 次运行:
运行 1

第二次运行:
运行 2

第三次运行:
运行 3

相关内容