对于我的思维导图,我想用箭头替换连接末尾的“火山”。
由于连接应该是弯曲的,因此我使用这个答案。我尝试了很多次,但不幸的是,我对 tikz/pgf 的了解不足以正确绘制箭头。我认为箭头最好定义在第二座火山最初的定义处。此时,我在代码中留下了相关注释。
以下是我目前所掌握的信息:
\documentclass[tikz,border=0pt]{standalone}
\usetikzlibrary{positioning, mindmap}
\makeatletter
\newdimen\pgfutil@tempdimc
\pgfdeclaredecoration{circle connection boomerang}{initial}
{
\state{initial}[width=0pt,next state=boomerang]
{
{
\pgftransformxshift{-\pgfkeysvalueof{/pgf/decoration/start radius}}%
\pgftransformrotate{\pgfdecorationsegmentaspect}%%%
\pgfpathmoveto{\pgfpointpolar{\pgfdecorationsegmentangle}{\pgfkeysvalueof{/pgf/decoration/start radius}}}
\pgfpatharc{\pgfdecorationsegmentangle}{-\pgfdecorationsegmentangle}{\pgfkeysvalueof{/pgf/decoration/start radius}}
\pgfutil@tempcnta=-\pgfdecorationsegmentangle\relax
\advance\pgfutil@tempcnta by90\relax
\pgfmathsetlength\pgfutil@tempdima{\pgfkeysvalueof{/pgf/decoration/start radius}}
\pgfmathsetlength\pgfutil@tempdimb{\pgfdecorationsegmentamplitude}
\pgfpathcurveto
{\pgfpointadd
{\pgfpointpolar{-\pgfdecorationsegmentangle}{\pgfkeysvalueof{/pgf/decoration/start radius}}}
{\pgfpointpolar{\the\pgfutil@tempcnta}{.25\pgfutil@tempdima}}}
{\pgfqpoint{1.25\pgfutil@tempdima}{-.5\pgfutil@tempdimb}}
{\pgfqpoint{1.5\pgfutil@tempdima}{-.5\pgfutil@tempdimb}}
\pgfpathlineto{\pgfpoint{1.5\pgfutil@tempdima}{.5\pgfutil@tempdimb}}
\pgfutil@tempcnta=\pgfdecorationsegmentangle\relax
\advance\pgfutil@tempcnta by-90\relax
\pgfpathcurveto
{\pgfpoint{1.25\pgfutil@tempdima}{.5\pgfutil@tempdimb}}
{\pgfpointadd
{\pgfpointpolar{\pgfdecorationsegmentangle}{\pgfkeysvalueof{/pgf/decoration/start radius}}}
{\pgfpointpolar{\the\pgfutil@tempcnta}{.25\pgfutil@tempdima}}}
{\pgfpointpolar{\pgfdecorationsegmentangle}{\pgfkeysvalueof{/pgf/decoration/start radius}}}
\pgfpathclose
}
}
\state{boomerang}[width=0pt,next state=end]
{
\pgfmathsetlength\pgfutil@tempdima{\pgfkeysvalueof{/pgf/decoration/start radius}}%
\pgfmathsetlength\pgfutil@tempdimb{\pgfkeysvalueof{/pgf/decoration/end radius}}%
\pgfmathsetlength\pgfutil@tempdimc{\pgfdecorationsegmentamplitude}%
\pgftransformxshift{-\pgfutil@tempdima}
\pgfpathmoveto
{\pgfpointadd
{\pgfpointpolar{\pgfdecorationsegmentaspect}{1.5\pgfutil@tempdima}}
{\pgfpointpolar{\pgfdecorationsegmentaspect-90}{.5\pgfutil@tempdimc}}}
\pgftransformxshift{\pgfdecoratedremainingdistance+\pgfutil@tempdima+\pgfutil@tempdimb}
\pgfpathquadraticcurveto
{\pgfpoint{-.5\pgfdecoratedremainingdistance-\pgfutil@tempdimb}{(.5\pgfdecoratedremainingdistance+.5\pgfutil@tempdima+.5\pgfutil@tempdimb)*tan(\pgfdecorationsegmentaspect)-.5\pgfutil@tempdimc}}
{\pgfpointadd
{\pgfpointpolar{-\pgfdecorationsegmentaspect}{-1.5\pgfutil@tempdimb}}
{\pgfpointpolar{-\pgfdecorationsegmentaspect-90}{.5\pgfutil@tempdimc}}}
\pgfpathlineto{\pgfpointadd
{\pgfpointpolar{-\pgfdecorationsegmentaspect}{-1.5\pgfutil@tempdimb}}
{\pgfpointpolar{-\pgfdecorationsegmentaspect+90}{.5\pgfutil@tempdimc}}}
\pgftransformxshift{-\pgfdecoratedremainingdistance-\pgfutil@tempdima-\pgfutil@tempdimb}
\pgfpathquadraticcurveto
{\pgfpoint{.5\pgfdecoratedremainingdistance+\pgfutil@tempdima}{(.5\pgfdecoratedremainingdistance+.5\pgfutil@tempdima+.5\pgfutil@tempdimb)*tan(\pgfdecorationsegmentaspect)+.5\pgfutil@tempdimc}}
{\pgfpointadd
{\pgfpointpolar{\pgfdecorationsegmentaspect}{1.5\pgfutil@tempdima}}
{\pgfpointpolar{\pgfdecorationsegmentaspect+90}{.5\pgfutil@tempdimc}}}
\pgfpathclose
}
\state{end}[width=0pt,next state=final]
{
{
% the arrow should be defined here
%
% original code producing the "volcano"
% \pgftransformxshift{\pgfdecoratedremainingdistance}%
% \pgftransformxscale{-1}%
% \pgftransformxshift{-\pgfkeysvalueof{/pgf/decoration/end radius}}%
% \pgftransformrotate{\pgfdecorationsegmentaspect}%%%
% \pgfpathmoveto{\pgfpointpolar{\pgfdecorationsegmentangle}{\pgfkeysvalueof{/pgf/decoration/end radius}}}
% \pgfpatharc{\pgfdecorationsegmentangle}{-\pgfdecorationsegmentangle}{\pgfkeysvalueof{/pgf/decoration/end radius}}
% \pgfutil@tempcnta=-\pgfdecorationsegmentangle\relax
% \advance\pgfutil@tempcnta by90\relax
% \pgfmathsetlength\pgfutil@tempdima{\pgfkeysvalueof{/pgf/decoration/end radius}}
% \pgfmathsetlength\pgfutil@tempdimb{\pgfdecorationsegmentamplitude}%
% \pgfpathcurveto
% {\pgfpointadd
% {\pgfpointpolar{-\pgfdecorationsegmentangle}{\pgfkeysvalueof{/pgf/decoration/end radius}}}
% {\pgfpointpolar{\the\pgfutil@tempcnta}{.25\pgfutil@tempdima}}}
% {\pgfqpoint{1.25\pgfutil@tempdima}{-.5\pgfutil@tempdimb}}
% {\pgfqpoint{1.5\pgfutil@tempdima}{-.5\pgfutil@tempdimb}}
% \pgfpathlineto{\pgfpoint{1.5\pgfutil@tempdima}{.5\pgfutil@tempdimb}}
% \pgfutil@tempcnta=\pgfdecorationsegmentangle\relax
% \advance\pgfutil@tempcnta by-90\relax
% \pgfpathcurveto
% {\pgfpoint{1.25\pgfutil@tempdima}{.5\pgfutil@tempdimb}}
% {\pgfpointadd
% {\pgfpointpolar{\pgfdecorationsegmentangle}{\pgfkeysvalueof{/pgf/decoration/end radius}}}
% {\pgfpointpolar{\the\pgfutil@tempcnta}{.25\pgfutil@tempdima}}}
% {\pgfpointpolar{\pgfdecorationsegmentangle}{\pgfkeysvalueof{/pgf/decoration/end radius}}}
% \pgfpathclose
}
}
\state{final}
{}
}
\tikzoption{circle connection boomerang switch color}{\tikz@parse@switch@boomerang#1\pgf@unique}
\def\tikz@parse@switch@boomerang from (#1) to (#2) by #3\pgf@unique{%
\tikzset{to path={%
\pgfextra{%
\tikz@lib@mindmap@check{\tikztostart}%
\tikz@compute@circle@radii\tikz@compute@segmentamplitude%
\global\let\tikz@lib@save@start=\tikztostart%
\global\let\tikz@lib@save@target=\tikztotarget%
\pgfkeysgetvalue{/pgf/decoration/start radius}\pgf@temp%
\global\let\tikz@lib@saved@start@radius=\pgf@temp%
\pgfkeysgetvalue{/pgf/decoration/end radius}\pgf@temp%
\global\let\tikz@lib@saved@end@radius=\pgf@temp%
}%
[every circle connection bar]
decorate [decoration={circle connection boomerang,aspect=#3}]
{ -- (\tikztotarget) \tikztonodes}
},
append after command={
[fill=none,draw=none,path picture=\tikz@lib@shade@pic]
\pgfextra{
\pgfutil@colorlet{tikz@switch@from}{#1}%
\pgfutil@colorlet{tikz@switch@to}{#2}%
}
}
}
}
\pgfdeclarehorizontalshading[tikz@switch@from,tikz@switch@to]{tikz@shade@bar}{10000bp}{%
color(0pt)=(tikz@switch@from);
color(100bp)=(tikz@switch@to)}
\tikzset{%
concept color and bend/.code 2 args=
{
\let\tikz@old@concept@color=\tikz@concept@color%
\def\tikz@edge@to@parent@path{
(\tikzparentnode)
to[circle connection boomerang switch color=from (\tikz@old@concept@color) to (#1) by #2]
(\tikzchildnode)}
\def\tikz@concept@color{#1}%
}
}
\begin{document}
\begin{tikzpicture}
\node[draw, circle, red] (n) {$n$};
\node[draw, circle] (m) [below = of n] {$m$};
\draw (n) to[circle connection boomerang switch color=from (red) to (black) by -5] (m);
\end{tikzpicture}
\end{document}
制作
结果应该是这样的:
答案1
我可能忽略了一些东西,但这似乎看起来很正确(从不同角度测试):
\documentclass[tikz,border=0pt]{standalone}
\usetikzlibrary{positioning, mindmap}
\makeatletter
\newdimen\pgfutil@tempdimc
\pgfdeclaredecoration{circle connection boomerang}{initial}
{
\state{initial}[width=0pt,next state=boomerang]
{
{
\pgftransformxshift{-\pgfkeysvalueof{/pgf/decoration/start radius}}%
\pgftransformrotate{\pgfdecorationsegmentaspect}%%%
\pgfpathmoveto{\pgfpointpolar{\pgfdecorationsegmentangle}{\pgfkeysvalueof{/pgf/decoration/start radius}}}
\pgfpatharc{\pgfdecorationsegmentangle}{-\pgfdecorationsegmentangle}{\pgfkeysvalueof{/pgf/decoration/start radius}}
\pgfutil@tempcnta=-\pgfdecorationsegmentangle\relax
\advance\pgfutil@tempcnta by90\relax
\pgfmathsetlength\pgfutil@tempdima{\pgfkeysvalueof{/pgf/decoration/start radius}}
\pgfmathsetlength\pgfutil@tempdimb{\pgfdecorationsegmentamplitude}
\pgfpathcurveto
{\pgfpointadd
{\pgfpointpolar{-\pgfdecorationsegmentangle}{\pgfkeysvalueof{/pgf/decoration/start radius}}}
{\pgfpointpolar{\the\pgfutil@tempcnta}{.25\pgfutil@tempdima}}}
{\pgfqpoint{1.25\pgfutil@tempdima}{-.5\pgfutil@tempdimb}}
{\pgfqpoint{1.5\pgfutil@tempdima}{-.5\pgfutil@tempdimb}}
\pgfpathlineto{\pgfpoint{1.5\pgfutil@tempdima}{.5\pgfutil@tempdimb}}
\pgfutil@tempcnta=\pgfdecorationsegmentangle\relax
\advance\pgfutil@tempcnta by-90\relax
\pgfpathcurveto
{\pgfpoint{1.25\pgfutil@tempdima}{.5\pgfutil@tempdimb}}
{\pgfpointadd
{\pgfpointpolar{\pgfdecorationsegmentangle}{\pgfkeysvalueof{/pgf/decoration/start radius}}}
{\pgfpointpolar{\the\pgfutil@tempcnta}{.25\pgfutil@tempdima}}}
{\pgfpointpolar{\pgfdecorationsegmentangle}{\pgfkeysvalueof{/pgf/decoration/start radius}}}
\pgfpathclose
}
}
\state{boomerang}[width=0pt,next state=end]
{
\pgfmathsetlength\pgfutil@tempdima{\pgfkeysvalueof{/pgf/decoration/start radius}}%
\pgfmathsetlength\pgfutil@tempdimb{10pt}% % <-- changeable
\pgfmathsetlength\pgfutil@tempdimc{\pgfdecorationsegmentamplitude}%
\pgftransformxshift{-\pgfutil@tempdima}
\pgfpathmoveto
{\pgfpointadd
{\pgfpointpolar{\pgfdecorationsegmentaspect}{1.5\pgfutil@tempdima}}
{\pgfpointpolar{\pgfdecorationsegmentaspect-90}{.5\pgfutil@tempdimc}}}
\pgftransformxshift{\pgfdecoratedremainingdistance+\pgfutil@tempdima+\pgfutil@tempdimb}
\pgfpathquadraticcurveto
{\pgfpoint{-.5\pgfdecoratedremainingdistance-\pgfutil@tempdimb}{(.5\pgfdecoratedremainingdistance+.5\pgfutil@tempdima+.5\pgfutil@tempdimb)*tan(\pgfdecorationsegmentaspect)-.5\pgfutil@tempdimc}}
{\pgfpointadd
{\pgfpointpolar{-\pgfdecorationsegmentaspect}{-1.5\pgfutil@tempdimb}}
{\pgfpointpolar{-\pgfdecorationsegmentaspect-90}{.5\pgfutil@tempdimc}}}
\pgfpathlineto{\pgfpointadd
{\pgfpointpolar{-\pgfdecorationsegmentaspect}{-1.5\pgfutil@tempdimb}}
{\pgfpointpolar{-\pgfdecorationsegmentaspect+90}{.5\pgfutil@tempdimc}}}
\pgftransformxshift{-\pgfdecoratedremainingdistance-\pgfutil@tempdima-\pgfutil@tempdimb}
\pgfpathquadraticcurveto
{\pgfpoint{.5\pgfdecoratedremainingdistance+\pgfutil@tempdima}{(.5\pgfdecoratedremainingdistance+.5\pgfutil@tempdima+.5\pgfutil@tempdimb)*tan(\pgfdecorationsegmentaspect)+.5\pgfutil@tempdimc}}
{\pgfpointadd
{\pgfpointpolar{\pgfdecorationsegmentaspect}{1.5\pgfutil@tempdima}}
{\pgfpointpolar{\pgfdecorationsegmentaspect+90}{.5\pgfutil@tempdimc}}}
\pgfpathclose
}
\state{end}[width=0pt,next state=final]
{
{
\pgftransformxshift{\pgfdecoratedremainingdistance}%
\pgftransformxscale{-1}
\pgfmathsetlength\pgfutil@tempdima{10pt}%
\pgftransformxshift{-\pgfutil@tempdima}%
\pgfpathmoveto{\pgfpointpolar{\pgfdecorationsegmentaspect}{\pgfutil@tempdima}}
\pgfpathlineto{\pgfpointadd
{\pgfpointpolar{\pgfdecorationsegmentaspect-90}{-2pt}} % <-- changeable
{\pgfpointpolar{\pgfdecorationsegmentaspect}{1.5*\pgfutil@tempdima}}}
\pgfpathlineto{\pgfpointadd
{\pgfpointpolar{\pgfdecorationsegmentaspect-90}{2pt}} % <-- changeable
{\pgfpointpolar{\pgfdecorationsegmentaspect}{1.5*\pgfutil@tempdima}}}
\pgfpathclose
}
}
\state{final}
{}
}
\tikzoption{circle connection boomerang switch color}{\tikz@parse@switch@boomerang#1\pgf@unique}
\def\tikz@parse@switch@boomerang from (#1) to (#2) by #3\pgf@unique{%
\tikzset{to path={%
\pgfextra{%
\tikz@lib@mindmap@check{\tikztostart}%
\tikz@compute@circle@radii\tikz@compute@segmentamplitude%
\global\let\tikz@lib@save@start=\tikztostart%
\global\let\tikz@lib@save@target=\tikztotarget%
\pgfkeysgetvalue{/pgf/decoration/start radius}\pgf@temp%
\global\let\tikz@lib@saved@start@radius=\pgf@temp%
\pgfkeysgetvalue{/pgf/decoration/end radius}\pgf@temp%
\global\let\tikz@lib@saved@end@radius=\pgf@temp%
}%
[every circle connection bar]
decorate [decoration={circle connection boomerang,aspect=#3}]
{ -- (\tikztotarget) \tikztonodes}
},
append after command={
[fill=none,draw=none,path picture=\tikz@lib@shade@pic]
\pgfextra{
\pgfutil@colorlet{tikz@switch@from}{#1}%
\pgfutil@colorlet{tikz@switch@to}{#2}%
}
}
}
}
\pgfdeclarehorizontalshading[tikz@switch@from,tikz@switch@to]{tikz@shade@bar}{10000bp}{%
color(0pt)=(tikz@switch@from);
color(100bp)=(tikz@switch@to)}
\tikzset{%
concept color and bend/.code 2 args=
{
\let\tikz@old@concept@color=\tikz@concept@color%
\def\tikz@edge@to@parent@path{
(\tikzparentnode)
to[circle connection boomerang switch color=from (\tikz@old@concept@color) to (#1) by #2]
(\tikzchildnode)}
\def\tikz@concept@color{#1}%
}
}
\begin{document}
\begin{tikzpicture}
\node[draw, circle, red] (n) {$n$};
\node[draw, circle] (m) [below = of n] {$m$};
\draw (n) to[circle connection boomerang switch color=from (red) to (black) by 20] (m);
\end{tikzpicture}
\end{document}
请注意,我需要更改状态中的一行boomerang
(第一个注释所在的行changeable
)以使箭头固定大小,而不管它指向的节点的大小。
目前,箭头的大小在样式中是硬编码的,这可能不是最佳的。您可以通过更改注释标记的行中的值10pt
和-2pt
来调整箭头的大小和宽度。2pt
changeable
另请注意,原始代码中似乎有一个错误此代码所基于的答案:如果将角度设置为更高的值,例如50
,渐变将不再填充整个箭头,并且某些部分将变得透明,因此不可见。遗憾的是,我还没有找到解决这个问题的方法。