适合相邻节点的节点大小

适合相邻节点的节点大小

我尝试使用下面的代码绘制数据包的帧格式。我的问题是指定所有minimum width=xx节点的大小真的很烦人。有没有办法让方框尽可能小(适合里面的文本)并将它们相对地放在一起?我尝试了 fit 库,但这并没有真正让它变得更容易。当我设置时,文本周围inner sep = 0pt不再有空间。否则,拟合的节点太大。我无法相信我的用例如此奇怪。我必须制作几个这样的图形,任何使其更容易的改进都将不胜感激。

\documentclass{standalone}

\usepackage{siunitx}
\sisetup{locale = DE, binary-units=true, per-mode=symbol-or-fraction, fraction-function=\tfrac}

\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{positioning}

\begin{document}

\begin{tikzpicture}[
    node distance = 0cm, auto,
    outer sep = 0pt,
    anchor=north west,
    element/.style={
        draw,
        fill=white,
        rectangle,
        align = center},
    5mm/.style={
        minimum height = 0.6cm},
    10mm/.style={
        minimum height = 1.2cm},
    15mm/.style={
        minimum height = 1.8cm},
    length/.style={
        draw,
        fill=white,
        rectangle,
        align = center,
        minimum height = 0.6cm},
    layer1/.style={
        fill=gray!20},
    layer2/.style={
        fill=gray!10},
    l1e/.style={
        fill=blue!20},
    l2e/.style={
        fill=red!20},
    opte/.style={
        fill=yellow!20},
    phye/.style={
        fill=green!20}]

\node[element,l1e , 15mm, minimum width=1.6cm] at (0,0) (SOF){Start of\\Frame};
\node[length,l1e, below = of SOF, minimum width=1.6cm](SOF-size){\SI{1}{\bit}};

\node[element,l2e , 10mm, minimum width=1.5cm] at ($(SOF.north east)+(0,-0.6)$) (id){ID};
\node[length,l2e , below = of id, minimum width=1.5cm] (Id-size){\SI{11}{\bit}};

\node[element,l2e , 10mm, right = of id, minimum width=1.3cm] (remote){Remote};
\node[length,l2e , below = of remote, minimum width=1.3cm] (remote-size){\SI{1}{\bit}};

\node[element,l2e , 10mm, right = of id, minimum width=1.6cm] (remote){Remote};
\node[length,l2e , below = of remote, minimum width=1.6cm] (remote-size){\SI{1}{\bit}};

\node[element, opte, 10mm, right = of remote, minimum width=1.6cm] (idext){ID Ext.};
\node[length, opte, below = of idext, minimum width=1.6cm] (idext-size){\SI{1}{\bit}};

\node[element, opte, 10mm, right = of idext, minimum width=1.6cm] (idb){ID (B)};
\node[length, opte, below = of idb, minimum width=1.6cm] (idb-size){\SI{18}{\bit}};

\node[element, opte, 10mm, right = of idb, minimum width=1.6cm] (remoteb){Remote};
\node[length, opte, below = of remoteb, minimum width=1.6cm] (remoteb-size){\SI{1}{\bit}};

\node[element,l2e , 10mm, right = of remoteb, minimum width=2cm] (reserved){Reserviert};
\node[length,l2e , below = of reserved, minimum width=2cm] (reserved-size){\SI{1}{\bit}};

\node[element,l2e , 10mm, right = of reserved, minimum width=2cm] (reserved2){Reserviert};
\node[length,l2e , below = of reserved2, minimum width=2cm] (reserved2-size){\SI{1}{\bit}};

\node[element,l2e , 10mm, right = of reserved2, minimum width=1.5cm] (length){Länge};
\node[length,l2e , below = of length, minimum width=1.5cm] (length-size){\SI{4}{\bit}};

\node[element,l2e , 5mm, minimum width=13.4cm] at (SOF.north east) (header){CAN Header: \SI{18}{\bit} bzw. \SI{36}{\bit}};

\node[element,l2e , 15mm, minimum width=3cm] at (header.north east)(payload){Nutzdaten};
\node[length,l2e , below = of payload, minimum width=3cm] (payload-size){\SIrange{0}{8}{\byte}};

\node[element,l2e , 15mm, right = of payload, minimum width=1.5cm] (crc){CRC};
\node[length,l2e , below = of crc, minimum width=1.5cm] (crc-size){\SI{15}{\bit}};

\node[element,l2e , 15mm, right = of crc, minimum width=1.4cm] (crcdelim){CRC\\Delim.};
\node[length,l2e , below = of crcdelim, minimum width=1.4cm] (crcdelim-size){\SI{1}{\bit}};

\node[element,l1e , 15mm, right = of crcdelim, minimum width=1.7cm] (ack){Acknow-\\ledge};
\node[length,l1e , below = of ack, minimum width=1.7cm] (ack-size){\SI{1}{\bit}};

\node[element,l1e , 15mm, right = of ack, minimum width=1.4cm] (ackdelim){ACK\\Delim.};
\node[length,l1e , below = of ackdelim, minimum width=1.4cm] (ackdelim-size){\SI{1}{\bit}};

\node[element,l1e , 15mm, right = of ackdelim, minimum width=1.4cm] (eof){End of\\Frame};
\node[length,l1e , below = of eof, minimum width=1.4cm] (eof-size){\SI{7}{\bit}};

\node[element, phye, 15mm, right = of eof, minimum width=1.4cm] (ifs){Inter\\Frame\\Space};
\node[length, phye, below = of ifs, minimum width=1.4cm] (ifs-size){\SI{3}{\bit}};

\node[element, layer1, 10mm, minimum width=25.4cm] at ($(SOF.north west)+(0,1.2)$) (layer1){};
\node[below right] at (layer1.north west) {Layer 1};
\node[below] at (layer1.north) {CAN Paket: \SI{44}{\bit} bzw. \SI{64}{\bit} bis \SI{108}{\bit} bzw. \SI{128}{\bit} (hinzu kommt bit Stuffing)};

\node[element, layer2, 5mm, minimum width=19.3cm] at ($(header.north west)+(0,0.6)$) (layer2){};
\node[below right] at (layer2.north west) {Layer 2};
\node[below] at (layer2.north) {CAN Frame: \SI{34}{\bit} bzw. \SI{54}{\bit} bis \SI{98}{\bit} bzw. \SI{118}{\bit}};

\end{tikzpicture}

\end{document}

结果

答案1

它花费的时间比我最初想象的要长,但我学到了很多东西。

第一个轻松定位所有节点的想法是使用matrix。它会自动定位所有节点,但它们会保留其实际大小(宽度和高度),并且以后很难绘制和填充模拟类似大小节点的分区。

然后我决定使用一个chain按照一定规则自动放置节点的,不需要明确地写出right = ... of

棘手的部分是如何定义一个双节点,其中两个部分具有相同的宽度但不同的高度。使用的解决方案是定义一个node带有字段名称的节点和一个带有位信息的标签。有了nodesouter sep=0ptnode distance=0pt

\begin{scope}[%
    start chain = Frame going below right, 
    node distance = 0pt and 0pt]
    \node[F2={1 bit}{blue}, text width=12mm] {Start of frame};
    \node[F1={11 bit}{red}, text width=1cm] {ID};
    \node[F1={1 bit}{red}] {Remote};
    ...

产生了这个:

在此处输入图片描述

有必要text width对诸如节点IDCRC标签比节点宽的字段施加一些限制。

下一步是如何绘制图层信息。这已在fit库帮助和拟合节点的帮助下完成inner sep=0pt。拟合节点的内容已放置在其中labels

这产生了完美边界调整的节点:

在此处输入图片描述

终于完成了位信息在背景层上的绘制和矩形填充:

    \begin{scope}[on background layer]
        \foreach \i [count=\ni] in {blue, red, red, yellow, yellow, yellow, 
                    red, red, red, red, red, red, blue, blue, blue, green}
            \draw[fill=\i!30] (Frame-\ni.south east) rectangle (Frame-\ni.west|-l\ni.south);
    \end{scope}

在此处输入图片描述

就这样!

最终结果如下:

在此处输入图片描述

完整代码如下:

\documentclass[tikz,border=2mm]{standalone} 
\usetikzlibrary{positioning, chains, fit, backgrounds}
\usepackage[english]{babel}
\usepackage{lmodern}

\begin{document}
\begin{tikzpicture}[%
    Fbase/.style = {on chain, draw, anchor=south west, 
        align=center, outer sep=0pt},
    F1/.style 2 args={Fbase, 
        label={[name=l\tikzchaincount]below:#1},
        fill=#2!30, minimum height=1.2cm},
    F2/.style 2 args={Fbase, 
        label={[name=l\tikzchaincount]below:#1},
        fill=#2!30, minimum height=1.8cm},
    ]

    \begin{scope}[%
        start chain = Frame going below right, 
        node distance = 0pt and 0pt]
        \node[F2={1 bit}{blue}, text width=12mm] {Start of frame};
        \node[F1={11 bit}{red}, text width=1cm] {ID};
        \node[F1={1 bit}{red}] {Remote};
        \node[F1={1 bit}{yellow}] {ID Ext.};
        \node[F1={18 bit}{yellow}] {ID (B)};
        \node[F1={1 bit}{yellow}] {Remote};
        \node[F1={1 bit}{red}] {Reserviert};
        \node[F1={1 bit}{red}] {Reserviert};
        \node[F1={4 bit}{red}] {Lnge};
        \node[F2={0B to 8B}{red}] {Nutzdaten};
        \node[F2={15 bit}{red}, text width=10mm] {CRC};
        \node[F2={1 bit}{red}, text width=12mm] {CRC Delim.};
        \node[F2={1 bit}{blue}, text width=14mm] {Acknow-\\ ledge};
        \node[F2={1 bit}{blue}, text width=14mm] {ACK\\  Delim.};
        \node[F2={7 bit}{blue}, text width=14mm] {End of Frame};
        \node[F2={3 bit}{green}, text width=14mm] {Inter Frame Space};
    \end{scope}

    \node[draw, fit=(Frame-1.north east) (Frame-9.north east), fill=red!40, 
        inner sep=0pt, label=center:{CAN Header: 18 bit bzw. 36 bit}] (C1) {};

    \node[draw, fit={(Frame-1.north west) ([yshift=12mm]Frame-15.north east)}, 
        inner sep=0pt, fill=gray!50, 
        label={[anchor=north]above:{CAN Paket: 44 bit bzw. 64 bit bis 108 bit bzw. 128 bit (hinzu kommt bit Stuffing)}}, 
        label={[anchor=north west, yshift=2mm]178:{Layer 1}}] (C3) {};

    \node[draw, fit={(Frame-1.north east) ([yshift=6mm]Frame-12.north east)}, 
        inner sep=0pt, fill=gray!30, 
        label=center:{CAN Frame: 34 bit bzw. 54 bit bis 98 bit bzw. 118 bit}, 
        label={[anchor=west]left:{Layer 2}}] (C2) {};

    \begin{scope}[on background layer]
        \foreach \i [count=\ni] in {blue, red, red, yellow, yellow, yellow, 
                    red, red, red, red, red, red, blue, blue, blue, green}
            \draw[fill=\i!30] (Frame-\ni.south east) rectangle (Frame-\ni.west|-l\ni.south);
    \end{scope}

\end{tikzpicture}
\end{document}

答案2

这里有一个解决方案,使用tabular而不是tikzpicture。说这是简单的方法可能是在撒谎。但至少不必对列的宽度进行硬编码。文本到垂直线的距离由 控制\tabcolsep

在此处输入图片描述

\documentclass[border=2mm]{standalone}
\usepackage[utf8]{inputenc}
\usepackage{siunitx}
\sisetup{locale = DE, binary-units=true,
  per-mode=symbol-or-fraction, fraction-function=\tfrac}
\usepackage{multirow,bigstrut}
\usepackage[table]{xcolor}
\usepackage{hhline}
\newcommand{\minitab}[1]{\begin{tabular}{@{}c@{}}#1\end{tabular}}
\colorlet{lgray}{gray!20}
\colorlet{llgray}{gray!10}
\colorlet{lblue}{blue!20}
\colorlet{lred}{red!20}
\colorlet{lyellow}{yellow!20}
\colorlet{lgreen}{green!20}
\newcommand\lgray{\cellcolor{lgray}}
\newcommand\llgray{\cellcolor{llgray}}
\newcommand\lblue{\cellcolor{lblue}}
\newcommand\lred{\cellcolor{lred}}
\newcommand\lyellow{\cellcolor{lyellow}}
\newcommand\lgreen{\cellcolor{lgreen}}
\begin{document}
{\tabcolsep=1pt
\begin{tabular}{|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|}
\hhline{*{15}-}%\cline{1-15}
  \multicolumn{1}{|l}{\lgray Layer 1}
  & \multicolumn{14}{c|}{\lgray CAN Paket: \SI{44}{\bit} bzw. \SI{64}{\bit} bis
    \SI{108}{\bit} bzw. \SI{128}{\bit} (hinzu kommt bit Stuffing)\bigstrut}
    & \multicolumn{1}{c}{}
\\\hhline{|>{\arrayrulecolor{lgray}}->{\arrayrulecolor{black}}|*{11}-|%
           >{\arrayrulecolor{lgray}}*{3}->{\arrayrulecolor{black}}|}%\cline{2-12}
  \lgray
  & \multicolumn{2}{l}{\llgray Layer 2}
    & \multicolumn{9}{c|}{\llgray CAN Frame: \SI{34}{\bit} bzw. \SI{54}{\bit} bis
      \SI{98}{\bit} bzw. \SI{118}{\bit}\bigstrut}
      & \multicolumn{3}{c|}{\lgray}
        & \multicolumn{1}{c}{}
\\\hline
  \lblue
  & \multicolumn{8}{c|}{\lred CAN Header: \SI{18}{\bit} bzw. \SI{36}{\bit}\bigstrut}
    & \lred
      & \lred
        & \lred
          & \lblue
            & \lblue
              & \lblue
                & \lgreen
\\\hhline{|>{\arrayrulecolor{lblue}}->{\arrayrulecolor{black}}|*8-|%
           *3{>{\arrayrulecolor{lred}}->{\arrayrulecolor{black}}|}%
           *3{>{\arrayrulecolor{lblue}}->{\arrayrulecolor{black}}|}%
           >{\arrayrulecolor{lgreen}}->{\arrayrulecolor{black}}|}%\cline{2-9}
  \lblue
  & \lred
    & \lred
     & \lyellow
       & \lyellow
         & \lyellow
           & \lred
             & \lred
               & \lred
                 & \lred
                   & \lred
                     & \lred
                       & \lblue
                         & \lblue
                           & \lblue
                             & \lgreen
\\
  \lblue\multirow{-3}[2]*{\minitab{Start of\\Frame}}
  & \lred\multirow{-2}*{ID}
    & \lred\multirow{-2}*{Remote}
      & \lyellow\multirow{-2}*{ID Ext.}
        & \lyellow\multirow{-2}*{ID (B)}
          & \lyellow\multirow{-2}*{Remote}
            & \lred\multirow{-2}*{Reserviert}
              & \lred\multirow{-2}*{Reserviert}
                & \lred\multirow{-2}*{Länge}
                  & \lred\multirow{-3}[4]*{Nutzdaten}
                    & \lred\multirow{-3}[4]*{CRC}
                      & \lred\multirow{-3}[4]*{\minitab{CRC\\Delim.}}
                        & \lblue\multirow{-3}[4]*{\minitab{Acknow-\\ledge}}
                          & \lblue\multirow{-3}[4]*{\minitab{ACK\\Delim.}}
                            & \lblue\multirow{-3}[4]*{\minitab{End of\\Frame}}
                              & \lgreen\multirow{-3}[4]*{\minitab{Inter\\Frame\\Space}}
\\\hline
  \lblue\SI{1}{\bit}\bigstrut
  & \lred\SI{11}{\bit}
    & \lred\SI{1}{\bit}
      & \lyellow\SI{1}{\bit}
        & \lyellow\SI{18}{\bit}
          & \lyellow\SI{1}{\bit}
            & \lred\SI{1}{\bit}
              & \lred\SI{1}{\bit}
                & \lred\SI{4}{\bit}
                  & \lred\SIrange{0}{8}{\byte}
                    & \lred\SI{15}{\bit}
                      & \lred\SI{1}{\bit}
                        & \lblue\SI{1}{\bit}
                          & \lblue\SI{1}{\bit}
                            & \lblue\SI{7}{\bit}
                              & \lgreen\SI{3}{\bit}
\\\hline
\end{tabular}}
\end{document}

相关内容