使用更吸引人的线条样式连接节点

使用更吸引人的线条样式连接节点

为了使箭头更具吸引力,我使用以下线条弯曲样式代码来控制箭头的绘制方式。

\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不在节点的右侧)。

由于您的示例仅使用未旋转的节点之间的奇异边,具有明确定义的指南针锚点并且大小相同,因此不存在任何边缘情况。


让我解释:

  1. 找到第一个和最后一个扭结:

    (\tikztostart)
      -- coordinate[at start, shift=(#3:<distance>))] (@auxs)
    +(#3:+1pt)
    

    这会将右边(如果它是一个节点) 放置在方向的coordinate边界 ( at start= pos = 0) 处,然后将其沿同一方向移动。\tikztostart#3<distance>

  2. 如果中间部分应该与节点中心相关,我们只需使用calc通路修饰剂查找@aux

  3. 如果中间部分应该与节点的边界相关(与中间部分正交),我们需要应用与 1 中相同的“技巧”来找到这些其他边界点@auxS@auxT

    通过这个,我们可以做与2中相同的事情来查找@aux

  4. 从那时起,它只是-|/|-路径运算符-|/|-坐标规格


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}

在此处输入图片描述

相关内容