在 TikZ 矩阵中执行多行/多列单元格时空单元格的对齐问题

在 TikZ 矩阵中执行多行/多列单元格时空单元格的对齐问题

这是一个已经讨论过的问题这里这里。讨论的解决方案之一是使用fit覆盖空单元格。但是,在尝试时,它显示了空单元格和其他单元格之间的对齐问题。这是讨论线程中的 MWE,其中对齐问题出在:

\documentclass[xcolor=dvipsnames, 14pt]{beamer}
\usepackage{lmodern}
\usepackage{tikz} 
\usetikzlibrary{matrix, fit}

\begin{document}
\begin{frame}
  \begin{tikzpicture} [
      block/.style ={rectangle
                      %,text width=6em
                      , draw
                      , minimum height=4em
                      , minimum width=4em
                      , outer sep=0pt}
    ]
    \matrix (table) [%
      matrix of nodes
      , nodes in empty cells
      , ampersand replacement=\&
      , nodes=block
    ] {%
      A \& B \& C \& D \\
      E \&   \&   \& G \\
      H \& I \& J \&   \\
      K \& L \& M \&   \\
   };
    %\node[fit=(table-2-2)(table-2-3), inner sep=0pt]{F};
    %\node[fit=(table-3-4)(table-4-4), inner sep=0pt]{N};
  \end{tikzpicture}
\end{frame}
\end{document}

在此处输入图片描述

为什么我需要多列单元格?我实际上想绘制以下堆叠 在此处输入图片描述

我设法在 tikz 中完成了此操作,但代码非常不优雅(xshift、yshfit 之类的调整)。我希望 Matrix 可以作为更好的解决方案,但遇到了上述对齐问题。以下是我调整解决方案的 MWE:

\documentclass[xcolor=dvipsnames, 14pt]{beamer}
\usepackage{lmodern}
\usepackage{tikz} 
\usetikzlibrary{matrix, fit}

\begin{document}
\begin{frame}

  \centering
  \footnotesize
  \begin{tikzpicture}[
      , every node/.style={
                  , rectangle, rounded corners=1mm  % the shape 
                  , very thick , draw % the border 
                  , fill=orange!50
       }]
    \node [minimum width=.6\textwidth] (a) {AAAA};
    \node [minimum width=.3\textwidth] (b) at (a.north) [xshift=-16mm, yshift=4mm] {B};
    \node [minimum width=.07\textwidth] (c) at (b.east) [xshift=5mm] {CCC};
    \node [minimum width=.20\textwidth] (d) at (c.east) [xshift=12mm] {DDDDD};
  \end{tikzpicture}
\end{frame}

\end{document}

答案1

对于对齐问题,您可以使用键text heighttext depthrow sepcolumn sep

\documentclass[xcolor=dvipsnames, 14pt]{beamer}
\usepackage{lmodern}
\usepackage{tikz} 
\usetikzlibrary{matrix, fit}

\begin{document}
\begin{frame}
  \begin{tikzpicture} [
      block/.style ={rectangle
                      , draw
                      , text height=2em
                      , minimum width=4em,
                      , text depth=1em
                      , outer sep=0pt}
    ]
    \matrix (table) [%
      matrix of nodes
      , nodes in empty cells
      , ampersand replacement=\&
      , nodes=block
      , row sep=-\pgflinewidth
      , column sep=-\pgflinewidth
    ] {%
      A \& B \& C \& D \\
      E \&   \&   \& G \\
      H \& I \& J \&   \\
      K \& L \& M \&   \\
   };
  \end{tikzpicture}
\end{frame}
\end{document}

在此处输入图片描述

对于其他布局,借用一些杰克的代码来自他的回答创建一个适合其他两个节点水平宽度的节点)来自动计算更宽的节点:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{positioning,calc,fit}

\definecolor{myorange}{RGB}{250,192,116}

\pgfkeys{
    /tikz/node distance/.append code={
        \pgfkeyssetvalue{/tikz/node distance value}{#1}
    }
}

\newcommand\widernode[5][myorange]{
\node[
        #1,
        inner sep=0pt,
        shift=($(#2.south)-(#2.north)$),
        yshift=-\pgfkeysvalueof{/tikz/node distance value},
        fit={(#2) (#3)},
        line width=1pt,
        label=center:{\sffamily\bfseries#4}] (#5) {};
}

\begin{document}

\begin{tikzpicture}[node distance=5pt,outer sep=0pt,
block/.style={
  line width=1pt,
  draw=black,
  fill=myorange,
  rounded corners,
  text width=#1,
  font={\sffamily\bfseries},
  align=center,
  text height=12pt,
  text depth=9pt
},
block/.default=1.5cm
]
\node[block=3cm] (a) {AAA};
\node[block=4.5cm,right=of a] (b) {BBB};
\node[block,right=of b] (c) {CCC};
\widernode[block]{a}{c}{DDD}{d}
\end{tikzpicture}

\end{document}

在此处输入图片描述

答案2

下面链接答案中的代码包含在positioning-plus图书馆在第二个例子中,其用途超出了链接答案所提供的内容。


对齐问题有两个原因:

  1. matrix of nodes样式将矩阵中每个节点的锚点设置为base(通常是您想要的)。
  2. 空单元格是空的,因此空文本框的基线与节点的中心高度相同,因此会稍微低一点对齐。

可以通过center再次使用锚点来恢复此操作,但如果所有节点文本的高度和深度不相同,此操作将失败(如果其中一个节点的文本比 宽,则会发生类似情况<minimum width> - 2 <inner xsep>)。对于普通的单行文本,您可以\strut在每个节点中使用 来修复此问题,并应用键font

对于多列和多行,我实际上会将其设置nodes in empty cells为 false 并使用未绘制的节点(以便它稍后可以用作参考但不可见)。而不是fit,我会使用我的span密钥我的另一个答案TikZ:使节点高度跨越其他几个节点span样式仅设置正确的minimum widths 和minimum heights,位置必须用at (fit bounding box)(由键创建的伪节点)设置span。因为它不会改变text depth,或者text height文本的垂直位置不会改变。

代码

\documentclass[tikz,convert=false]{standalone}
\usepackage{lmodern}
\usetikzlibrary{matrix, positioning-plus}
\tikzset{
  block/.style={
    rectangle,
    draw,
    minimum height=4em,
    minimum width=4em,
    outer sep=0pt,
%    anchor=center,
    font=\strut},
  empty cells are empty/.style={
    execute at empty cell={\node[draw=none,fill=none]{};},
    nodes in empty cells=false
  },
  overlapping lines in matrices/.style={
    row sep=-\pgflinewidth,
    column sep=-\pgflinewidth}
}
\begin{document}
\begin{tikzpicture}
    \matrix (table) [%
      matrix of nodes,
      ampersand replacement=\&,
      nodes=block,
      overlapping lines in matrices,
      empty cells are empty
    ] {%
      A \& B \& C \& D \\
      e \&   \&   \& G \\
      H \& I \& J \&   \\
      K \& L \& M \&   \\
   };
    \node[block, span=(table-2-2)(table-2-3)] at (fit bounding box) {F};
    \node[block, span=(table-3-4)(table-4-4)] at (fit bounding box) {N};
\end{tikzpicture}
\end{document}

输出

在此处输入图片描述


对于您的其他图表,我再次建议不要使用和fit进行手​​动调整。最好使用带有其键的库(是语法)。xshiftyshiftpositioningnode distance<vertical distance> and <horizontal distance>

对于第一个代码示例,节点bcd以水平方式放置right=of <previous node>(该chains库可以帮助创建许多节点)。positioning使用上面链接的答案中的代码再次改进了键,以便您可以使用below=of -(b)(d)这意味着新节点将在 和 下方创建bd并且具有 ,minimal width以便它水平跨越两个节点。

第二个示例首先放置a节点,然后将节点bd放置在上方,但西对齐和东对齐,因此键为west aboveeast above。这些键由我的positioning-plus图书馆
就像above将自己的锚点设置为south而将引用节点的锚点设置为一样northwest above将自己的锚点设置为north west而将引用节点的锚点设置为south west。定位键的概述可以在我的另一个答案

然后,第四个节点就简单地放置在和c的边界之间。这不会检查s 的有效性,也不会使用水平节点距离。bdminimum width

代码

\documentclass[tikz,convert=false]{standalone}
\usepackage{lmodern}
\usetikzlibrary{positioning-plus}
\tikzset{
  node distance=+2mm and +2mm,
  every node/.style={
    rectangle,
    rounded corners=1mm,
    very thick,
    draw,
    fill=orange!50
  }
}
\begin{document}
\begin{tikzpicture}% Code A
  \node[minimum width=+.3\textwidth]  (b) {B};
  \node[minimum width=+.07\textwidth, right=of b] (c) {C};
  \node[minimum width=+.2\textwidth, right=of c] (d) {D};
  \node[below=of -(b)(d)] (a) {AAAA};
\end{tikzpicture}
\begin{tikzpicture}% Code B
  \node[minimum width=.6\textwidth] (a) {AAAA};
  \node[minimum width=+.3\textwidth, west above=of a] (b) {B};
  % or: \node[minimum width=+.3\textwidth, above=of a.north west, anchor=south west] (b) {B};
  \node[minimum width=+.2\textwidth, east above=of a] (d) {D};
  % or: \node[minimum width=+.2\textwidth, above=of a.north east, anchor=south east] (d) {D};
  \path (b) -- node[minimum width=+.07\textwidth] (c) {C} (d);% places the node (c) in the
                                                              % middle between (b) and (d)
\end{tikzpicture}
\end{document}

输出

输出 A

在此处输入图片描述

输出 B

在此处输入图片描述

相关内容