我尝试使用下面的代码来实现一个简单的 uml 序列图,它可以工作,但有两件事需要改进:
- 消息回复描述文字应该更改为左上方。
- 节点距离应根据下面的文本宽度进行调整。(当前代码使用定义来手动调整)。
代码:
\documentclass[border=3mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{positioning}
\tikzset{
class/.style={%
inner sep=2pt,
minimum width=1ex,
},
arr/.style={%
draw,-stealth
},
}
\newcommand{\actor}[3][]{%
\node[class,#1] (#2) {#3};
\draw [line width=1] (#2.south west) -- (#2.south east);
}
\begin{document}
\begin{tikzpicture}[font=\fontsize{5}{6}\selectfont]
\def\nodes{%
A/2cm/jack,
B/2cm/mary,
C/2cm/john
}
\def\links{%
A/B/message one,
B/C/message two loooooooooooong,
C/A/message three
}
\foreach \name/\pos/\desc [count=\i from 0,remember=\name as \prev] in \nodes {%
\ifnum \i=0
\actor[]{\name}{\desc};
\else
\actor[right=\pos of \prev]{\name}{\desc};
\fi
\message{debugme \i -> \prev};
}
\def\dy{-.3cm}
\foreach \from/\to/\desc [count=\i] in \links {
\draw[arr] ([yshift=\i*\dy]\from.south) -- coordinate(P) ([yshift=\i*\dy]\to.south)
node[pos=0,above right] {\tiny \desc};
}
\foreach \name/\pos/\desc in \nodes {%
\draw[dashed] (\name.south) -- (\name|-P);
}
\end{tikzpicture}
\end{document}
答案1
像这样?
使用基本代码,节点放置使用 Ti钾Z 库chains
和positioning
:
\documentclass[border=3mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{arrows.meta,
chains,
positioning}
\begin{document}
\begin{tikzpicture}[
node distance = 5mm and 22mm,
start chain = going right,
arr/.style = {-{Straight Barb[scale=0.8]}, semithick},
lbl/.style = {font=\scriptsize\linespread{0.84}\relax,
inner sep=1pt, fill=white,
text width=22mm, align=center, above},
N/.style = {font=\footnotesize,
append after command = {\pgfextra{\let\LN\tikzlastnode
\draw[ultra thick, line cap=round]
(\LN.south west) -- (\LN.south east);
}% end \pgfextra
},% end after command
on chain
},
]
\foreach \i [count=\j] in {Jack, Mary, John}
{
\node (n\j) [N] {\i};
\draw[very thin, densely dashed] (n\j.south) -- ++ (0,-1.7);
}
\path (n1.south) -- ++ (0,-5mm) coordinate (A)
-- ++ (0,-5mm) coordinate (B)
-- ++ (0,-5mm) coordinate (C);
\draw[arr] (A) -- node[lbl] {message one} (A -| n2);
\draw[arr] (B -| n2) -- node[lbl] {message two loooooooooooong} (B -| n3);
\draw[arr] (C -| n3) -- node[lbl] {message three} (C);
\end{tikzpicture}
\end{document}
附录:
- 显然我误解了这个问题(并且低估了 OP 的目的......),- - 下面的 MWE 现在满足了 OP 的要求
\documentclass[border=3mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{arrows.meta,
positioning}
\usepackage{calc}
\newlength{\dx}
\begin{document}
\begin{tikzpicture}[
node distance = 5mm,
arr/.style = {-{Straight Barb[scale=0.8]}, semithick},
lbl/.style = {font=\small,above},
N/.style = {font=\small,
append after command = {\pgfextra{\let\LN\tikzlastnode
\draw[ultra thick, line cap=round]
(\LN.south west) -- (\LN.south east);
}% end \pgfextra
},% end after command
},
]
\def\dy{5mm}
\node (n1) [N] {Jacki};
\setlength{\dx}{\widthof{message two}}
\node (n2) [N, right=\dx of n1] {Mary};
\setlength{\dx}{\widthof{message two is very long, consequently distance between nodes too}}
\node (n3) [N, right=\dx of n2] {John};
\foreach \i in {1,2,3}
\draw[very thin, densely dashed] (n\i.south) -- ++ (0,-21mm);
\coordinate[below=of n1.south] (A);
\coordinate[below=of A] (B);
\coordinate[below=of B] (C);
\draw[arr] (A) -- node[lbl] {message one} (A -| n2);
\draw[arr] (B -| n2) -- node[lbl] {message two is very long, consequently distance between nodes too} (B -| n3);
\draw[arr] (C -| n3) -- node[lbl] {message three} (C);
\end{tikzpicture}
\end{document}