Clipping issue with TikZ fading

shadingtikz-pathtikz-pgf

Following Issue with fade-no-fill.sty, I wanted to try implementing @hpekristiansen solution. I’m giving a more complete code here because I have text nodes on the paths actually.

\documentclass[tikz]{standalone}

\usetikzlibrary{shapes, fadings}

\begin{document}
\begin{tikzpicture}
    \node [red,draw,thick,ellipse] (S) at (-3,0) {Solide};
    \node [blue,draw,thick,ellipse] (L) at (3,0) {Liquide};
    \node [green,draw,thick,ellipse] (G) at (0,{3*sqrt(3)}) {Gaz};
    \draw [thick,-latex,red,path fading=north,postaction={draw,green,path fading=south}] (S) to[bend left] node [midway,above,sloped,black] {Sublimation} (G);
    \draw [thick,-latex,green,path fading=south,postaction={draw,blue,path fading=north}] (G) to[bend left] node [midway,above,sloped,black] {Liquéfaction} (L);
    \draw [thick,-latex,blue,path fading=west,postaction={draw,red,path fading=east}] (L) to[bend left] node [midway,below,sloped,black] {Solidification} (S);
    \draw [thick,-latex,red,path fading=east,postaction={draw,blue,path fading=west}] (S) to node [midway,above,sloped,black] {Fusion} (L);
    \draw [thick,-latex,blue,path fading=north,postaction={draw,green,path fading=south}] (L) to node [midway,below,sloped,black] {Vaporisation} (G);
    \draw [thick,-latex,green,path fading=south,postaction={draw,red,path fading=north}] (G) to node [midway,below,sloped,black] {Condensation} (S);
\end{tikzpicture}
\end{document}

Output (in a correct PDF viewer, see comments under https://tex.stackexchange.com/a/615816/56823) is as follow:
code output

I have two issues with it:

  1. Clipping on the horizontal line. @hpekristiansen mentionned this issue and a workaround (also in Fading arrows in TikZ), but actually clipping is not limited to the arrow : the text node also is clipped! I could of course also redraw it, but this is far from ideal. Note that using arrows.meta and substituting -latex for -Latex does not fixes the issue here (but is a fine change if required for a proper solution).
  2. Fading on text nodes. I’ve tried adding path fading=none to the nodes options, but for no results. I can of course draw the text nodes separately, but again this is far from ideal.

Best Answer

I'm not sure how much of a "hack" this counts as, but as is often the case much of the hackery can be hidden in styles so that it doesn't feel too bad.

The two issues are addressed as follows:

  1. So that the nodes are not affected by the fading, but are still defined on the relevant path, then the fading is implemented in two postactions (the choice of postaction is arbitrary - it could be two preactions, or one pre and one post). The path itself is not drawn. To make this a bit slicker, I've defined a style path bifading that takes two directions and two styles (in this, the styles are just colours but they could be more general).

  2. To ensure that the arrowheads are visible, I define a key that extends the bounding box. Specifically, at the end of the path then this key simulates adding a point that is positioned at the point (-5pt,5pt) relative to the end of the path and rotated so that the x direction points along the path and the y direction is normal to the path. Note that this does not actually extend the path, it just extends the bounding box. The transformation to this coordinate system is achieved by way of my spath3 library.

\documentclass[tikz,border=10pt]{standalone}
%\url{https://tex.stackexchange.com/q/615945/86}
\usetikzlibrary{
  shapes,
  fadings,
  arrows.meta,
  spath3
}

\tikzset{
  path bifading/.style n args={4}{
    postaction={
      every bifading/.try,
      path fading=#1,%
      #3%
    },
    postaction={
      every bifading/.try,
      path fading=#2,%
      #4%
    }
  },
  every bifading/.style={draw,thick},
  fade arrow/.style={
    #1,
    spath/transform to={current}{1},
    extend bounding box={(-5pt,5pt)}
  }
}

\makeatletter
\tikzset{
  extend bounding box/.code={%
    \tikz@scan@one@point\pgfutil@firstofone#1\relax
    \pgf@protocolsizes{\pgf@x}{\pgf@y}%
  }
}
\makeatother

\begin{document}
\begin{tikzpicture}
\node [red,draw,thick,ellipse] (S) at (-3,0) {Solide};
\node [blue,draw,thick,ellipse] (L) at (3,0) {Liquide};
\node [green,draw,thick,ellipse] (G) at (0,{3*sqrt(3)}) {Gaz};
\path
[path bifading={north}{south}{red}{green}]
(S) to[bend left] node [midway,above,sloped,black] {Sublimation} (G)
[fade arrow={-Latex}]
;
\path
[path bifading={south}{north}{green}{blue}]
(G) to[bend left] node [midway,above,sloped,black] {Liquéfaction} (L)
[fade arrow={-Latex}]
;
\path
[path bifading={west}{east}{blue}{red}]
(L) to[bend left] node [midway,below,sloped,black] {Solidification} (S)
[fade arrow={-Latex}]
;
\path
[path bifading={east}{west}{red,-Latex}{blue}]
(S) to node [midway,above,sloped,black] {Fusion} (L)
[fade arrow={-Latex}]
;
\path
[path bifading={north}{south}{blue}{green}]
(L) to node [midway,below,sloped,black] {Vaporisation} (G)
[fade arrow={-Latex}]
;
\path
[path bifading={south}{north}{green}{red}]
(G) to node [midway,below,sloped,black] {Condensation} (S)
[fade arrow={-Latex}]
;
\end{tikzpicture}
\end{document}

Path fading with arrows and nodes


As @hpekristiansen suggests in the comments, the angle of the fading can be figured out from the path's endpoints. There's a bit of work to be done to make the path accessible in the postaction, but it's doable.

\documentclass[tikz,border=10pt]{standalone}
%\url{https://tex.stackexchange.com/q/615945/86}
\usetikzlibrary{
  shapes,
  fadings,
  decorations.markings,
  arrows.meta,
  spath3
}

\tikzset{
  path bifading/.style 2 args={
    postaction={
      spath/save action path,
      extend bounding box,
      every bifading/.try,
      path fading=west,
      set fading angle,
      #1%
    },
    postaction={
      spath/save action path,
      extend bounding box,
      every bifading/.try,
      path fading=east,%
      set fading angle,
      #2%
    }
  },
  every bifading/.style={draw,thick},
}

\makeatletter
\ExplSyntaxOn
\tikzset{
  spath/save~ action~ path/.code={
    \cs_set_eq:cN {\__tikzspath_path_name:n {action}} \tikz@actions@path
  }
}
\ExplSyntaxOff

\tikzset{
  extend bounding box/.code={%
    \begingroup
    \tikzset{spath/transform to={action}{1}}
    \tikz@scan@one@point\pgfutil@firstofone(-5pt,5pt)\relax
    \pgf@protocolsizes{\pgf@x}{\pgf@y}%
    \endgroup
  },
  set fading angle/.code={%
    \tikz@scan@one@point\pgfutil@firstofone(spath cs:action 0)\relax
    \pgf@xa=\pgf@x
    \pgf@ya=\pgf@y
    \tikz@scan@one@point\pgfutil@firstofone(spath cs:action 1)\relax
    \pgfmathsetmacro\fading@angle{atan2(\pgf@ya - \pgf@y, \pgf@xa - \pgf@x)}%
    \tikzset{fading angle=\fading@angle}%
  }
}
\makeatother

\begin{document}
\begin{tikzpicture}
\node [red,draw,thick,ellipse] (S) at (-3,0) {Solide};
\node [blue,draw,thick,ellipse] (L) at (3,0) {Liquide};
\node [green,draw,thick,ellipse] (G) at (0,{3*sqrt(3)}) {Gaz};
\path
[
  -Latex,
  path bifading={red}{green}
]
(S) to[bend left] node [midway,above,sloped,black] {Sublimation} (G)
;
\path
[
  -Latex,
  path bifading={green}{blue}
]
(G) to[bend left] node [midway,above,sloped,black] {Liquéfaction} (L)
;
\path
[
  -Latex,
  path bifading={blue}{red}
]
(L) to[bend left] node [midway,below,sloped,black] {Solidification} (S)
;
\path
[
  -Latex,
  path bifading={red}{blue}
]
(S) to node [midway,above,sloped,black] {Fusion} (L)
;
\path
[
  -Latex,
  path bifading={blue}{green}
]
(L) to node [midway,below,sloped,black] {Vaporisation} (G)
;
\path
[
  -Latex,
  path bifading={green}{red}
]
(G) to node [midway,below,sloped,black] {Condensation} (S)
;
\end{tikzpicture}
\end{document}

path fading with automatic angle