为了使箭头更具吸引力,我使用以下线条弯曲样式代码来控制箭头的绘制方式。
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{arrows, calc, positioning}
\begin{document}
1
\begin{tikzpicture}
\tikzset{
-|-/.style={to path={(\tikztostart) -| ($(\tikztostart)!#1!(\tikztotarget)$) |- (\tikztotarget) \tikztonodes}},
-|-/.default=0.5,
|-|/.style={to path={(\tikztostart) |- ($(\tikztostart)!#1!(\tikztotarget)$) -| (\tikztotarget) \tikztonodes}},
|-|/.default=0.5,
}
\tikzset{block/.style={draw=green, fill=green!15, rectangle, rounded corners=.5em, align=center, minimum width=2cm, minimum height=1cm},}
\node [block] (aa) {aa};
\node [block, right=of aa] (bb) {bb};
\node [block, right=of bb] (cc) {cc};
\node [block, below=2cm of aa] (dd) {dd};
\node [block, right=of dd] (ee) {ee};
\node [block, right=of ee] (ff) {ff};
\path[draw, green, -latex, line width=.06cm] (aa) edge (bb) (bb) edge (cc) (cc.east) to [|-|] (dd.west) (dd) edge (ee) (ee) edge (ff);
\end{tikzpicture}
\vskip 1cm
2
\begin{tikzpicture}
\tikzset{
-|-/.style={to path={(\tikztostart) -| ($(\tikztostart)!#1!(\tikztotarget)$) |- (\tikztotarget) \tikztonodes}},
-|-/.default=0.5,
|-|/.style={to path={(\tikztostart) |- ($(\tikztostart)!#1!(\tikztotarget)$) -| (\tikztotarget) \tikztonodes}},
|-|/.default=0.5,
}
\tikzset{block/.style={draw=blue, fill=blue!15, rectangle, rounded corners=.5em, align=center, minimum width=2cm, minimum height=1cm},}
\node [block] (aa) {aa};
\node [block, right=of aa] (bb) {bb};
\node [block, right=of bb] (cc) {cc};
\node [block, below=2cm of aa] (dd) {dd};
\node [block, right=of dd] (ee) {ee};
\node [block, right=of ee] (ff) {ff};
\node [coordinate, right=.5cm of cc] (rright) {};
\node [coordinate, left=.5cm of dd] (lleft) {};
\path[draw, cyan, -latex, line width=.06cm] (aa) edge (bb) (bb) edge (cc) (cc.east) -- (rright) to [|-|] (lleft) -- (dd.west) (dd) edge (ee) (ee) edge (ff);
\end{tikzpicture}
\end{document}
在绿色图 1 中,使用的样式使线从节点 cc 直接向下延伸到节点 dd。
在蓝色图 2 中,为了获得更好看的箭头,我在节点 cc 的右侧和节点 dd 的左侧使用了附加节点。
是否可以定义其他线条样式使线先向右走再向下(而不是使用右侧的附加节点)。是否也应用相同的概念来向左走(而不是使用左侧的附加节点)?
答案1
你只需要重新定义一些风格。例如,让我们这样做
\tikzset
{
-|-/.style={to path={(\tikztostart) --++ (#1,0) |-
($(\tikztostart)!0.5!(\tikztotarget)$) -|
($(\tikztotarget)+(-#1,0)$) --
(\tikztotarget)}},
-|-/.default=0.5cm,
}
上述代码从第一个节点出发,移动到其右侧 0.5cm 处的点(默认 #1 = 0.5cm)。然后先沿垂直方向移动,再沿水平方向(|-
)移动到两个节点之间的中点。然后先沿水平方向移动,再沿垂直方向(-|
)移动到第二个节点左侧 0.5cm 处的点。最后到达第二个节点。
举个例子,只留下绘图的必要部分:
\documentclass[tikz,border=2mm]{standalone}
\usetikzlibrary{calc,positioning}
\tikzset
{
-|-/.style={to path={(\tikztostart) --++ (#1,0) |-
($(\tikztostart)!0.5!(\tikztotarget)$) -|
($(\tikztotarget)+(-#1,0)$) --
(\tikztotarget)}},
-|-/.default=0.5cm,
block/.style={draw=blue,fill=blue!15,rectangle,rounded corners=0.5em,
align=center,minimum width=2cm,minimum height=1cm}
}
\begin{document}
\begin{tikzpicture}
\tikzset{,}
\node [block] (aa) {aa};
\node [block, right=of aa] (bb) {bb};
\node [block, right=of bb] (cc) {cc};
\node [block, below=2cm of aa] (dd) {dd};
\node [block, right=of dd] (ee) {ee};
\node [block, right=of ee] (ff) {ff};
\path[draw,cyan,-latex,line width=0.06cm]
(aa) edge (bb)
(bb) edge (cc)
(cc.east) to [-|-] (dd.west)
(dd) edge (ee)
(ee) edge (ff);
\end{tikzpicture}
\end{document}
答案2
这是snakey
我最近为 TikZ-CD 提供的另一个密钥
并为您提供一个-|-
和一把|-|
钥匙,可以做以下几件事:
它们将第一个和最后一个扭结放置在
snakey distance
远离边界节点(这意味着您不必明确指定锚点)。该参数
#1
指定比率(无单位)或距离(有单位)- 在边界之间或
- 中心之间(
snakey from center
设置时)
这条路径的主要中间部分应该位于哪里。
如果指定一个较小的比率(如
0
)或较小的距离并激活snakey from center
路径可能会再次与节点相交(参见示例的最后一行)。该线的设置方式是
\tikztonodes
(即沿边缘放置的所有坐标,节点和图片)位于整个构造的中间部分。线总是从远离两个节点的相反方向开始。这就是程序
\pgfextra
计算的结果和\tikzsnakeysign(X)
宏控制的结果。
其中一种风格可以通过以下方式定义
|-|/.style={-|-={#1}, rotate=90}
但这可能会导致一些副作用。
一切路径计算都是在内部完成的,edge
它不会改变当前路径,也不会“抬起”笔。
这.expanded
是必要的,因为上面提到的edge
抓住他们自己的\tikztostart
/ \tikztotarget
(我们将忽略它)并且我们需要规避这一点。
这路径计算有必要找到一个节点的边界,而不需要某处硬编码适当的锚点(并且必须弄清楚使用哪一个),但它也允许旋转节点(可能.east
不在节点的右侧)。
由于您的示例仅使用未旋转的节点之间的奇异边,具有明确定义的指南针锚点并且大小相同,因此不存在任何边缘情况。
让我解释:
找到第一个和最后一个扭结:
(\tikztostart) -- coordinate[at start, shift=(#3:<distance>))] (@auxs) +(#3:+1pt)
这会将右边(如果它是一个节点) 放置在方向的
coordinate
边界 (at start
=pos = 0
) 处,然后将其沿同一方向移动。\tikztostart
#3
<distance>
如果中间部分应该与节点中心相关,我们只需使用
calc
的通路修饰剂查找@aux
。如果中间部分应该与节点的边界相关(与中间部分正交),我们需要应用与 1 中相同的“技巧”来找到这些其他边界点
@auxS
和@auxT
。通过这个,我们可以做与2中相同的事情来查找
@aux
。从那时起,它只是
-|
/|-
路径运算符和-|
/|-
坐标规格。
block
我从节点中删除了样式ff
,以显示不同的设置如何影响线条的结果。
我还添加了另一个小例子,展示了在较长的路径上的用法,其中|-|
只构成了其中的一部分,同时仍然正确地连接到周围的部分(因此我希望隐藏所有路径计算在一个边缘处):
\tikz\draw[line width=3mm] (0,0) -- ++(1,1) to[|-|] ++(1,1) -- ++(1,1);
代码
\documentclass[tikz]{standalone}
\usetikzlibrary{arrows.meta, calc, positioning}
\makeatletter
\newcommand*\tikzpointdiff[2]{%
\pgf@process{\pgfpointdiff{\tikz@scan@one@point\pgfutil@firstofone(#2)}
{\tikz@scan@one@point\pgfutil@firstofone(#1)}}}
\makeatother
\newif\iftikzsnakeyfromcenter
\tikzset{
snakey distance/.initial=.5cm,
snakey from center/.is if=tikzsnakeyfromcenter,
snakey/.style n args={9}{
to path={
\pgfextra
\tikzpointdiff{\tikztostart}{\tikztotarget}%
\expandafter\ifdim\csname pgf@#1\endcsname<0pt
\def\tikzsnakeysign{-}\else\def\tikzsnakeysign{}\fi
\expandafter\ifdim\csname pgf@#2\endcsname<0pt
\def\tikzsnakeysignX{-}\else\def\tikzsnakeysignX{}\fi
\endpgfextra % hide calculation inside another path wo interrupting current
[insert path/.expanded={edge[path only, to path={
(\tikztostart) -- coordinate[at start,
shift=(#3:{\tikzsnakeysign(\pgfkeysvalueof{/tikz/snakey distance})})
](@auxs) +(#3:+\tikzsnakeysign 1pt)
(\tikztotarget) -- coordinate[at start,
shift=(#4:{\tikzsnakeysign(\pgfkeysvalueof{/tikz/snakey distance})})
](@auxt) +(#4:+\tikzsnakeysign 1pt)
\iftikzsnakeyfromcenter
coordinate (@aux) at ($(\tikztostart)!{#9}!(\tikztotarget)$)
\else
(\tikztostart) -- coordinate[at start](@auxS)+(#5:+\tikzsnakeysignX 1pt)
(\tikztotarget)-- coordinate[at start](@auxT)+(#6:+\tikzsnakeysignX 1pt)
coordinate (@aux) at ($(@auxS)!{#9}!(@auxT)$)
\fi }]()}]% () = empty edge target, must be present
#7(@auxs#8@aux)--(@auxt#8@aux)\tikztonodes #8(\tikztotarget)}},
-|-/.style={snakey={x}{y}{right}{left}{down}{up} {-|}{|-}{#1}},
|-|/.style={snakey={y}{x}{up} {down}{left}{right}{|-}{-|}{#1}},
-|-/.default=.5, |-|/.default=.5}
\newcommand*\mytikzdiagram[1]{%
\node [block] (aa) {aa};
\node [block, right=of aa] (bb) {bb};
\node [block, right=of bb] (cc) {cc};
\node [block, below=of aa] (dd) {dd};
\node [block, right=of dd] (ee) {ee};
\node [draw, right=of ee] (ff) {ff};
\path[-Latex, line width=.06cm]
(aa) edge (bb) (bb) edge (cc) (cc) edge[#1] (dd)
(dd) edge (ee) (ee) edge (ff) (aa) edge[blue!50, #1, dashed](ff);}
\begin{document}
\tikz[row sep=5mm, column sep=5mm, every odd row/.style=snakey from center,
row 1/.style={font=\ttfamily, nodes={scale=3}}, column 1/.style={anchor=east},
row 4/.style={-|-/.default=.75cm, |-|/.default=.75cm},
row 5/.style={-|-/.default=.75cm, |-|/.default=.75cm},
block/.style={
draw=green, fill=green!15, rectangle, rounded corners=.5em, align=center,
minimum width=2cm, minimum height=1cm}]
\matrix{ & \node{|-|}; & \node{-|-}; \\
\node{.5 from border}; & \mytikzdiagram{|-|} & \mytikzdiagram{-|-} \\
\node{.5 from center}; & \mytikzdiagram{|-|} & \mytikzdiagram{-|-} \\
\node{.5cm from border}; & \mytikzdiagram{|-|} & \mytikzdiagram{-|-} \\
\node{.5cm from center}; & \mytikzdiagram{|-|} & \mytikzdiagram{-|-} \\
};
\tikz\draw[line width=3mm] (0,0) -- (1,1) to[|-|] (2,3) -- (3,4);
\end{document}
输出
答案3
使用 Ti 的替代方案钾Z 库ext.paths.ortho
:
\documentclass[tikz, margin=3mm]{standalone}
\usetikzlibrary{arrows.meta,
calc, chains,
positioning}
\usetikzlibrary{ext.paths.ortho}
\makeatletter
\tikzset{suspend join/.code={\def\tikz@after@path{}}}
\makeatother
\begin{document}
\begin{tikzpicture}[
node distance = 12mm and 9mm,
start chain = going right,
arr/.style = {draw=cyan, -{Stealth[length=3mm]}, line width=0.8mm},
box/.style = {draw=blue, rounded corners=0.5em, fill=blue!15,
minimum height=1cm, minimum width=2cm, align=center,
on chain, join=by arr},
]
\begin{scope}[nodes={box, on chain}]
\node (aa) {aa};
\node (bb) {bb};
\node (cc) {cc};
%
\node [suspend join,
below=of aa] (dd) {cc};
\node (ee) {ee};
\node (ff) {ff};
\end{scope}
\coordinate[right=of cc] (aux1);
\coordinate[ left=of dd] (aux2);
\draw[arr] (cc) -- (aux1) |-| (aux2) -- (dd);
\end{tikzpicture}
\end{document}