我尝试使用下面的代码绘制数据包的帧格式。我的问题是指定所有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
带有字段名称的节点和一个带有位信息的标签。有了nodes
和outer sep=0pt
,node 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
对诸如节点ID
或CRC
标签比节点宽的字段施加一些限制。
下一步是如何绘制图层信息。这已在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}