是否可以自动使文本换行,以使其不会溢出到节点中?另一种方法是让节点自动移得更远以容纳更长的文本(尽可能保持我设置节点的方式,我希望尽可能避免手动输入坐标)。
尽管有时可以通过该text width
选项手动实现这一点,但在某些情况下也会导致文本偏离中心,因此没有必要。
梅威瑟:
\documentclass[12pt]{article}
\usepackage{tikz}
\usetikzlibrary{automata,positioning,arrows}
\begin{document}
\begin{tikzpicture}[shorten >=2pt,node distance=4cm,on grid,auto]
\node[state] (Rd) {Ready};
\node[state] (Rn) [above right =of Rd] {Run};
\node[state] (Bl) [below right =of Rd] {Blocked};
\node[state] (Nr) [below right =of Rn] {Dead};
\path[->]
(Rd) edge node[sloped, anchor=center, above] {Given a timeslice} (Rn)
(Rd) edge node[sloped, anchor=center, below] {Asks for I/O} (Bl)
(Rd) edge node {Gets killed by kernel} (Nr)
(Bl) edge node {Out of memory} (Nr);
\end{tikzpicture}
\end{document}
更新:问题示例text width
。请注意中心如何转移,即使使用了
anchor = center
(text width = 3cm
和)。text width = 2.7cm
答案1
事实上是可行的排队计算半径并强制文本宽度来执行此操作。
所需的方法是TikZ
let
命令(由库启用calc
)。
它基本上允许您对路径中的坐标进行算术运算:
手册中的一个例子是这样的:
\coordinate (a) at (rnd,rnd);
\coordinate (b) at (3-rnd,3-rnd);
\draw (a) -- (b);
\node (c) at (1,2) {x};
\draw let \p1 = ($ (a)!(c)!(b) - (c) $),
\n1 = {veclen(\x1,\y1)}
in circle [at=(c), radius=\n1];
由于坐标a
和位置随机,如果不用算术解决画一个刚好接触和b
之间线的圆的问题,就不可能对齐所画圆的大小。a
b
它let
基本上允许访问特定点的坐标x
并y
对其进行操作。结合该calc
库,您几乎可以无限地进行对齐、计算长度等操作。
在您的情况下,您需要计算它们之间的向量长度减去节点的半径。
\path[->]
let \p1 = ($(Rd)-(Bl)$), % Save length between centers of the nodes
\p2 = ($(Rd)-(Rd.south)+(Bl)-(Bl.south)$), % Calculate the radius
\n1 = {veclen(\x1,\y1)-veclen(\x2,\y2)} in % The allowed text width
(Rd) edge node[sloped,anchor=center,align=center,above,text width=\n1]
{Given a timeslice} (Rn) ...
这将自动调整两个节点之间的长度。
一个不同的例子node distance
是这样的:
\foreach \myx in {2.5cm,3cm,4cm,5cm} {
\begin{tikzpicture}[shorten >=2pt,node distance=\myx,on grid,auto]
\node[state] (Rd) {Ready};
\node[state] (Rn) [above right =of Rd] {Run};
\path[->]
let \p1 = ($(Rd)-(Rn)$),
\p2 = ($(Rd)-(Rd.south)+(Rn)-(Rn.south)$),
\n1 = {veclen(\x1,\y1)-veclen(\x2,\y2)} in
(Rd) edge node[sloped,anchor=center,align=center,above,text width=\n1]
{Given a timeslice} (Rn);
\end{tikzpicture}
}
得到下图:
对于您来说,您甚至可以创建一个新命令:
\def\mylet#1#2{%
let \p1 = ($(#1)-(#2)$),%
\p2 = ($(#1)-(#1.south)+(#2)-(#2.south)$), %
\n1 = {veclen(\x1,\y1)-veclen(\x2,\y2)} in %
}
\path
但是,这限制了您在每次建立连接时重新创建命令(请注意,您需要align=center
正确对齐路径,这是因为当文本太小时,文本宽度太大),尝试使用节点距离并查看结果。
\begin{tikzpicture}[shorten >=2pt,node distance=4cm,on grid,auto
,every node/.append style={align=center}]
\node[state] (Rd) {Ready};
\node[state] (Rn) [above right =of Rd] {Run};
\node[state] (Bl) [below right =of Rd] {Blocked};
\node[state] (Nr) [below right =of Rn] {Dead};
\path[->] \mylet{Rd}{Rn} (Rd)
edge node[sloped,anchor=center,above,text width=\n1]
{Given a timeslice} (Rn);
\path[->] \mylet{Rd}{Bl}
(Rd) edge node[sloped,anchor=center,below,text width=\n1]
{Asks for I/O} (Bl);
\path[->] \mylet{Rd}{Nr}
(Rd) edge node[text width=\n1]
{Gets killed by kernel} (Nr);
\path[->] (Bl) edge node {Out of memory} (Nr);
\end{tikzpicture}
举例说明
那么该命令如何let
起作用TikZ
?
考虑以下:
\coordinate (a) at (1,0);
\draw (a) -- ++(2,0);
这将创建一个名为的坐标a
,然后从a
到 加上两个单位进行绘制X
方向。精确的同样的绘图也可以这样实现:
\coordinate (a) at (1,0);
\draw[thick,dashed] let \p1 = (a) in (\p1) -- ++(2,0);
目前这显然不是最好的方法(前者更清晰,更简短)。但是,这允许对特定坐标的x
和y
坐标进行算术运算(在这种情况下,点a
或(1,0)
可用于后续点的计算。
最好的例子可能是逐步完成向您提供的解决方案:
let \p1 = ($(Rd)-(Bl)$)
与前面的例子一样,我们让\p1
成为在最外层括号内计算的坐标。在其中我们遇到了以下形式:
$(Rd)-(Bl)$
这是一个典型的从 中TikZ
减去 坐标的命令。在这种情况下,这些坐标指的是节点,在这种情况下,它们对应于节点的中心点,即圆的中心。因此,如果和定义如下:Rd
Bl
Rd
Bl
\node (Rd) at (1,1) {Rd};
\node (Bl) at (4,4) {Bl};
现在我们可以通过从 中减去 来计算指向 从Bl
到 的向量:Rd
Bl
Rd
\draw (0,0) -- ($(Rd)-(Bl)$); % Will draw (0,0) -- (-3,-3)
因此,在我给出的例子中,我们将有\p1 = (-3,-3)
。以下命令\p2 = ($(Rd)-(Rd.south)+(Bl)-(Bl.south)$)
获取下图中显示的点,并同时计算r_1
和r_2
向量并将它们相加。
现在我们有了从一个节点的中间到另一个节点的中间的向量和我们有一个向量,其长度等于两个节点的半径。
现在我们可以通过以下方法计算两个节点之间的长度:从节点中心向量中减去半径向量。
\n1 = {veclen(\x1,\y1)-veclen(\x2,\y2)}
如果更有意义的话,你也可以这样做:
...
let \p1 = ($(Rd)-(Rn)$), % Vector between centers
\p2 = ($(Rd)-(Rd.south)$), % Vector with length of `Rd` radius
\p3 = ($(Rn)-(Rn.south)$), % Vector with length of `Rn` radius
% (length between centers) - (radius of `Rd`) - (radius of `Rn`)
\n1 = {veclen(\x1,\y1)-veclen(\x2,\y2)-veclen(\x3,\y3)}
in ...
答案2
该选项text width
可用于指定要排版文本的框的宽度,这会导致该框中的自动换行(也许是连字符)。
但是,由于文本默认在该框内左对齐,即使该框正确位于行的中心,文本也可能会稍微向左移动。
\begin{tikzpicture}
\node[circle, draw] (A) at (0,0) {A};
\node[circle, draw] (B) at (4,0) {B};
\draw (A) -- (B) node[text width=3cm, above, midway]
{Some long text which will be wrapped};
\end{tikzpicture}
在文本后面阴影化的框有助于理解这种效果:
\begin{tikzpicture}
\node[circle, draw] (A) at (0,0) {A};
\node[circle, draw] (B) at (4,0) {B};
\draw (A) -- (B) node[text width=3cm, above, midway, fill=black!10]
{Some long text which will be wrapped};
\end{tikzpicture}
通过将文本置于框内居中可以缓解此问题。但是,这将禁用连字符,并会尝试使所有结果行的长度相同。\\
不过,您可以使用手动插入换行符。
\begin{tikzpicture}
\node[circle, draw] (A) at (0,0) {A};
\node[circle, draw] (B) at (4,0) {B};
\draw (A) -- (B) node[text width=3cm, above, midway, fill=black!10, align=center]
{Some long text which will be wrapped};
\end{tikzpicture}
最后,下面的代码展示了一种根据节点之间的距离自动计算文本框适当宽度的技术:
\usetikzlibrary{calc}
\def\connectwithlongtext#1#2#3#4{ % line options, start, end, text
\draw[#1]
let
\p1 = ($(#2)-(#3)$),
\n1 = {0.6*veclen(\x1,\y1)}
in (#2) -- (#3)
node[fill=black!5, midway, above, align=center, text width=\n1, sloped]
{#4};
}
\begin{tikzpicture}
\node[draw,circle] (A) at (0,0) {A};
\node[draw] (B) at (3,2) {B};
\node[draw] (C) at (4.5, -3) {C};
\connectwithlongtext{->}{A}{B}{Lorem ipsum and blah, blah, blah};
\connectwithlongtext{->}{A}{C}{Lorem ipsum and blah, blah, blah};
\end{tikzpicture}