4

Yes, I know there are several topics about, but no one referred to my case. While colormap seems works only with plots, how can I draw a multicolor curve with smooth gradient? This is my attempt:

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage{makecell}
\setcellgapes{5pt}
\usepackage{booktabs}
\usepackage{amsmath,amssymb,amsfonts,systeme,mathtools} 
\usepackage{pgfplots}
\usepackage{float}

\begin{document}

\begin{figure}[H]
\centering
\begin{tikzpicture}
  \begin{axis}[
  ticks=none,
  grid=none,
  xmin=0,xmax=100,
  ymin=0,ymax=100,
  axis lines = middle,
  set layers,
  xlabel={$t$},ylabel={$T$},
  x label style={at={(1,0)},right},
  y label style={at={(0,1)},above},
  colormap={redblue}{rgb255(0cm)=(255,0,0); rgb255(1cm)=(0,0,255)}
               ]
    \draw [ultra thick] (20,90) to[out=270,in=110] (25,60) to[out=335,in=115] (35,45) to[out=0,in=180] (70,45) to[out=305,in=150] (90,20);
    \node[inner sep=0pt, label={[outer sep=-2pt]45:A}] at (20,90) {} ;
    \node[label={[outer sep=-2pt]45:B}] at (25,60) {} ;
    \node[label={[outer sep=-2pt]45:C}] at (35,45) {} ;
    \node[label={[outer sep=-2pt]45:D}] at (70,45) {} ;
    \node[label={[outer sep=-2pt]45:E}] at (90,20) {} ;
    \addplot[only marks, mark options={solid,draw=green,fill=green}]
    coordinates {
    (20,90) (25,60) (35,45) (70,45) (90,20)
    };
    \end{axis}
\end{tikzpicture}
\end{figure}

\end{document}

enter image description here

Can you help me?

Thank you in advance

7

As you said, colormaps works with plots. In your code there is indeed a plot, but only for plotting the marks and hence not the line. This one is drawn with the \draw command inside the axis. Therefore, you have to add a gradient color to your line.

Gradient with two colors

For instance, using the solution by Mark Wibrow to How to draw an arrow with two colors? you can add a color gradient using \path and the defined shading path option in tikset. Then with left color=<color> and right color=<color> (or top color=<color> and bottom color=<color>) you have a gradient with only two colors.

Output:

enter image description here

Code:

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage{makecell}
\setcellgapes{5pt}
\usepackage{booktabs}
\usepackage{amsmath,amssymb,amsfonts,systeme,mathtools} 
\usepackage{pgfplots}
\usepackage{float}
\usetikzlibrary{decorations.markings,fadings}

%https://tex.stackexchange.com/questions/137357/how-to-draw-an-arrow-with-two-colors
\makeatletter
\newif\iftikz@shading@path

\tikzset{
    % There are three circumstances in which the fading sep is needed:
    % 1. Arrows which do not update the bounding box (which is most of them).
    % 2. Line caps/joins and mitres that extend outside the natural bounding 
    %    box of the path (these are not calculated by PGF).
    % 3. Other reasons that haven't been anticipated.
    fading xsep/.store in=\pgfpathfadingxsep,
    fading ysep/.store in=\pgfpathfadingysep,
    fading sep/.style={fading xsep=#1, fading ysep=#1},
    fading sep=0.0cm,
    shading path/.code={%
        % Prevent this stuff happning recursively.
        \iftikz@shading@path%
        \else%
        \tikz@shading@pathtrue%
        % \tikz@addmode installs the `modes' (e.g., fill, draw, shade) 
        % to be applied to the path. It isn't usualy for doing more
        % changes to the path's construction.
        \tikz@addmode{%
            \pgfgetpath\pgf@currentfadingpath%
            % Get the boudning box of the current path size including the fading sep
            \pgfextract@process\pgf@fadingpath@southwest{\pgfpointadd{\pgfqpoint{\pgf@pathminx}{\pgf@pathminy}}%
                {\pgfpoint{-\pgfpathfadingxsep}{-\pgfpathfadingysep}}}%%
            \pgfextract@process\pgf@fadingpath@northeast{\pgfpointadd{\pgfqpoint{\pgf@pathmaxx}{\pgf@pathmaxy}}%
                {\pgfpoint{\pgfpathfadingxsep}{\pgfpathfadingysep}}}%
            % Clear the path
            \pgfsetpath\pgfutil@empty%                          
            % Interrupt the path and picture to create a fading.
            \pgfinterruptpath%
            \pgfinterruptpicture%
            \begin{tikzfadingfrompicture}[name=.]
                \path [shade=none,fill=none, #1] \pgfextra{%
                    % Set the softpath. Any transformations in #1 will have no effect.
                    % This will *not* update the bounding box...
                    \pgfsetpath\pgf@currentfadingpath%
                    % ...so it is done manually.
                    \pgf@fadingpath@southwest
                    \expandafter\pgf@protocolsizes{\the\pgf@x}{\the\pgf@y}%
                    \pgf@fadingpath@northeast%
                    \expandafter\pgf@protocolsizes{\the\pgf@x}{\the\pgf@y}%
                };
                % Now get the bounding of the picture.
                \xdef\pgf@fadingboundingbox@southwest{\noexpand\pgfqpoint{\the\pgf@picminx}{\the\pgf@picminy}}%
                \xdef\pgf@fadingboundingbox@northeast{\noexpand\pgfqpoint{\the\pgf@picmaxx}{\the\pgf@picmaxy}}%
                %
            \end{tikzfadingfrompicture}%
            \endpgfinterruptpicture%
            \endpgfinterruptpath%
            % Install a rectangle that covers the shaded/faded path picture.                                
            \pgfpathrectanglecorners{\pgf@fadingboundingbox@southwest}{\pgf@fadingboundingbox@northeast}%
            % Make the fading happen.
            \def\tikz@path@fading{.}%
            \tikz@mode@fade@pathtrue%
            \tikz@fade@adjustfalse%10pt
            % Shift the fading to the mid point of the rectangle
            \pgfpointscale{0.5}{\pgfpointadd{\pgf@fadingboundingbox@southwest}{\pgf@fadingboundingbox@northeast}}%
            \edef\tikz@fade@transform{shift={(\the\pgf@x,\the\pgf@y)}}%
        }%
        \fi%
    }
}


\begin{document}

\begin{figure}[H]
\centering
\begin{tikzpicture}
  \begin{axis}[
  ticks=none,
  grid=none,
  xmin=0,xmax=100,
  ymin=0,ymax=100,
  axis lines = middle,
  set layers,
  xlabel={$t$},ylabel={$T$},
  x label style={at={(1,0)},right},
  y label style={at={(0,1)},above},
  %colormap={redblue}{rgb255(0cm)=(255,0,0); rgb255(1cm)=(0,0,255)}
               ]
    \path [left color=red, right color=blue, shading path={draw=transparent!0, ultra thick,}]
    (20,90) to[out=270,in=110] (25,60) to[out=335,in=115] (35,45) to[out=0,in=180] (70,45) to[out=305,in=150] (90,20);
%    \draw [ultra thick] (20,90) to[out=270,in=110] (25,60) to[out=335,in=115] (35,45) to[out=0,in=180] (70,45) to[out=305,in=150] (90,20);
    \node[inner sep=0pt, label={[outer sep=-2pt]45:A}] at (20,90) {} ;
    \node[label={[outer sep=-2pt]45:B}] at (25,60) {} ;
    \node[label={[outer sep=-2pt]45:C}] at (35,45) {} ;
    \node[label={[outer sep=-2pt]45:D}] at (70,45) {} ;
    \node[label={[outer sep=-2pt]45:E}] at (90,20) {} ;
    \addplot[only marks, mark options={solid,draw=green,fill=green}]
    coordinates {
    (20,90) (25,60) (35,45) (70,45) (90,20)
    };
    \end{axis}
\end{tikzpicture}
\end{figure}

\end{document}

Gradient with multicolors

For a multicolor gradient there is also a possibility. The aforementioned solution pass a gradient of two colors to the line color with the commands of the Shading library (Chapter 69, p.737). Therefore, if we are able to pass a multicolor gradient to Mark Wibrow´s solution, we have it done. Thankfully, Mark Wibrow gives us also the solution in the answer to How to draw gradient arrows with Tikz. Just combining both of them we can set a desired multicolor gradient.

Output with shading1:

enter image description here

Output with shading2:

enter image description here

Output with shading3:

enter image description here

Code:

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage{makecell}
\setcellgapes{5pt}
\usepackage{booktabs}
\usepackage{amsmath,amssymb,amsfonts,systeme,mathtools} 
\usepackage{pgfplots}
\usepackage{float}
\usetikzlibrary{decorations.markings,fadings}

%https://tex.stackexchange.com/questions/137357/how-to-draw-an-arrow-with-two-colors
\makeatletter
\newif\iftikz@shading@path

\tikzset{
    % There are three circumstances in which the fading sep is needed:
    % 1. Arrows which do not update the bounding box (which is most of them).
    % 2. Line caps/joins and mitres that extend outside the natural bounding 
    %    box of the path (these are not calculated by PGF).
    % 3. Other reasons that haven't been anticipated.
    fading xsep/.store in=\pgfpathfadingxsep,
    fading ysep/.store in=\pgfpathfadingysep,
    fading sep/.style={fading xsep=#1, fading ysep=#1},
    fading sep=0.0cm,
    shading path/.code={%
        % Prevent this stuff happning recursively.
        \iftikz@shading@path%
        \else%
        \tikz@shading@pathtrue%
        % \tikz@addmode installs the `modes' (e.g., fill, draw, shade) 
        % to be applied to the path. It isn't usualy for doing more
        % changes to the path's construction.
        \tikz@addmode{%
            \pgfgetpath\pgf@currentfadingpath%
            % Get the boudning box of the current path size including the fading sep
            \pgfextract@process\pgf@fadingpath@southwest{\pgfpointadd{\pgfqpoint{\pgf@pathminx}{\pgf@pathminy}}%
                {\pgfpoint{-\pgfpathfadingxsep}{-\pgfpathfadingysep}}}%%
            \pgfextract@process\pgf@fadingpath@northeast{\pgfpointadd{\pgfqpoint{\pgf@pathmaxx}{\pgf@pathmaxy}}%
                {\pgfpoint{\pgfpathfadingxsep}{\pgfpathfadingysep}}}%
            % Clear the path
            \pgfsetpath\pgfutil@empty%                          
            % Interrupt the path and picture to create a fading.
            \pgfinterruptpath%
            \pgfinterruptpicture%
            \begin{tikzfadingfrompicture}[name=.]
                \path [shade=none,fill=none, #1] \pgfextra{%
                    % Set the softpath. Any transformations in #1 will have no effect.
                    % This will *not* update the bounding box...
                    \pgfsetpath\pgf@currentfadingpath%
                    % ...so it is done manually.
                    \pgf@fadingpath@southwest
                    \expandafter\pgf@protocolsizes{\the\pgf@x}{\the\pgf@y}%
                    \pgf@fadingpath@northeast%
                    \expandafter\pgf@protocolsizes{\the\pgf@x}{\the\pgf@y}%
                };
                % Now get the bounding of the picture.
                \xdef\pgf@fadingboundingbox@southwest{\noexpand\pgfqpoint{\the\pgf@picminx}{\the\pgf@picminy}}%
                \xdef\pgf@fadingboundingbox@northeast{\noexpand\pgfqpoint{\the\pgf@picmaxx}{\the\pgf@picmaxy}}%
                %
            \end{tikzfadingfrompicture}%
            \endpgfinterruptpicture%
            \endpgfinterruptpath%
            % Install a rectangle that covers the shaded/faded path picture.                                
            \pgfpathrectanglecorners{\pgf@fadingboundingbox@southwest}{\pgf@fadingboundingbox@northeast}%
            % Make the fading happen.
            \def\tikz@path@fading{.}%
            \tikz@mode@fade@pathtrue%
            \tikz@fade@adjustfalse%10pt
            % Shift the fading to the mid point of the rectangle
            \pgfpointscale{0.5}{\pgfpointadd{\pgf@fadingboundingbox@southwest}{\pgf@fadingboundingbox@northeast}}%
            \edef\tikz@fade@transform{shift={(\the\pgf@x,\the\pgf@y)}}%
        }%
        \fi%
    }
}
\makeatother
%-------------------------------------------------------------------------------------
%https://tex.stackexchange.com/questions/197793/how-to-draw-gradient-arrows-with-tikz
\makeatletter
\def\createshadingfromlist#1#2#3{%
    \pgfutil@tempcnta=0\relax
    \pgfutil@for\pgf@tmp:={#3}\do{\advance\pgfutil@tempcnta by1}%
    \ifnum\pgfutil@tempcnta=1\relax%
    \edef\pgf@spec{color(0)=(#3);color(100)=(#3)}%
    \else%
    \pgfmathparse{50/(\pgfutil@tempcnta-1)}\let\pgf@step=\pgfmathresult%
    %
    \pgfutil@tempcntb=1\relax%
    \pgfutil@for\pgf@tmp:={#3}\do{%
        \ifnum\pgfutil@tempcntb=1\relax%
        \edef\pgf@spec{color(0)=(\pgf@tmp);color(25)=(\pgf@tmp)}%
        \else%
        \ifnum\pgfutil@tempcntb<\pgfutil@tempcnta\relax%
        \pgfmathparse{25+\pgf@step/4+(\pgfutil@tempcntb-1)*\pgf@step}%
        \edef\pgf@spec{\pgf@spec;color(\pgfmathresult)=(\pgf@tmp)}%
        \else%
        \edef\pgf@spec{\pgf@spec;color(75)=(\pgf@tmp);color(100)=(\pgf@tmp)}%
        \fi%
        \fi%
        \advance\pgfutil@tempcntb by1\relax%
    }%
    \fi%
    \csname pgfdeclare#2shading\endcsname{#1}{100}\pgf@spec%
}
\makeatother

\createshadingfromlist{shading1}{vertical}{red,yellow,green,cyan,blue}
\createshadingfromlist{shading2}{vertical}{red,green,yellow}
\createshadingfromlist{shading3}{vertical}{red,black,blue,green,cyan,orange,yellow}


\begin{document}

\begin{figure}[H]
\centering
\begin{tikzpicture}
  \begin{axis}[
  ticks=none,
  grid=none,
  xmin=0,xmax=100,
  ymin=0,ymax=100,
  axis lines = middle,
  set layers,
  xlabel={$t$},ylabel={$T$},
  x label style={at={(1,0)},right},
  y label style={at={(0,1)},above},
%  colormap={redblue}{rgb255(0cm)=(255,0,0); rgb255(1cm)=(0,0,255)}
               ]
    \path [shading=shading1, shading path={draw=transparent!0, ultra thick,}]
    (20,90) to[out=270,in=110] (25,60) to[out=335,in=115] (35,45) to[out=0,in=180] (70,45) to[out=305,in=150] (90,20);
%    \draw [ultra thick] (20,90) to[out=270,in=110] (25,60) to[out=335,in=115] (35,45) to[out=0,in=180] (70,45) to[out=305,in=150] (90,20);
    \node[inner sep=0pt, label={[outer sep=-2pt]45:A}] at (20,90) {} ;
    \node[label={[outer sep=-2pt]45:B}] at (25,60) {} ;
    \node[label={[outer sep=-2pt]45:C}] at (35,45) {} ;
    \node[label={[outer sep=-2pt]45:D}] at (70,45) {} ;
    \node[label={[outer sep=-2pt]45:E}] at (90,20) {} ;
    \addplot[only marks, mark options={solid,draw=green,fill=green}]
    coordinates {
    (20,90) (25,60) (35,45) (70,45) (90,20)
    };
    \end{axis}
\end{tikzpicture}
\end{figure}

\end{document}
4

This is a slightly different approach than in Ñako's nice answer in that you can specify the color (and the line width) as a function of the fraction of the path. You may think of this as a version of point meta, in which you can specify the meta as a function of the decorated path length. This code is based on this answer as well as this answer. The first example uses a linear dependence on the path length fraction, and the second one an oscillating function, and also features a varying line width. Please note also that you can use point meta to achieve this (see e.g. this answer), but then you cannot use bend left and friends.

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage{pgfplots}
\pgfplotsset{compat=1.16}
\usetikzlibrary{decorations}
\usepackage{float}
\pgfkeys{/pgf/decoration/.cd,
         start color/.store in=\startcolor,
         start color=black,
         end color/.store in=\endcolor,
         end color=black,
         varying line width steps/.initial=100
}
\pgfdeclaredecoration{width and color change}{initial}{
 \state{initial}[width=0pt, next state=line, persistent precomputation={%
   \pgfmathparse{\pgfdecoratedpathlength/\pgfkeysvalueof{/pgf/decoration/varying line width steps}}%
   \let\increment=\pgfmathresult%
   \def\x{0}%
 }]{}
 \state{line}[width=\increment pt,   persistent postcomputation={%
   \pgfmathsetmacro{\x}{\x+\increment}
   },next state=line]{%
   \pgfmathparse{varyinglw(\x/\pgfdecoratedpathlength)}
   \pgfsetlinewidth{\pgfmathresult pt}%
   \pgfpathmoveto{\pgfpointorigin}%
   \pgfmathsetmacro{\steplength}{1.4*\increment}
   \pgfpathlineto{\pgfqpoint{\steplength pt}{0pt}}%
   \pgfmathsetmacro{\y}{varyingcolor(100*(\x/\pgfdecoratedpathlength))}
   \pgfsetstrokecolor{\endcolor!\y!\startcolor}%
   \pgfusepath{stroke}%
 }
 \state{final}{%
   \pgfmathparse{varyinglw(1)}  
   \pgfsetlinewidth{\pgfmathresult pt}%
   \pgfpathmoveto{\pgfpointorigin}%
   \pgfmathsetmacro{\y}{varyingcolor(100*(\x/\pgfdecoratedpathlength))}
   \color{\endcolor!\y!\startcolor}%
   \pgfusepath{stroke}% 
 }
}
\begin{document}

\begin{figure}[H]
\centering
\begin{tikzpicture}[declare function={varyinglw(\x)=1;varyingcolor(\x)=\x;}]
  \begin{axis}[
  ticks=none,
  grid=none,
  xmin=0,xmax=100,
  ymin=0,ymax=100,
  axis lines = middle,
  set layers,
  xlabel={$t$},ylabel={$T$},
  x label style={at={(1,0)},right},
  y label style={at={(0,1)},above},
  colormap={redblue}{rgb255(0cm)=(255,0,0); rgb255(1cm)=(0,0,255)}
               ]
    \draw [decorate,decoration={width and color change,
    start color=red,end color=blue}] (20,90) to[out=270,in=110] (25,60) to[out=335,in=115] (35,45) to[out=0,in=180] (70,45) to[out=305,in=150] (90,20);
    \node[inner sep=0pt, label={[outer sep=-2pt]45:A}] at (20,90) {} ;
    \node[label={[outer sep=-2pt]45:B}] at (25,60) {} ;
    \node[label={[outer sep=-2pt]45:C}] at (35,45) {} ;
    \node[label={[outer sep=-2pt]45:D}] at (70,45) {} ;
    \node[label={[outer sep=-2pt]45:E}] at (90,20) {} ;
    \addplot[only marks, mark options={solid,draw=green,fill=green}]
    coordinates {
    (20,90) (25,60) (35,45) (70,45) (90,20)
    };
    \end{axis}
\end{tikzpicture}
\end{figure}

\begin{figure}[H]
\centering
\begin{tikzpicture}[declare
function={varyinglw(\x)=2+sin(360*\x);varyingcolor(\x)=50+50*sin(7.2*\x);}]
  \begin{axis}[
  ticks=none,
  grid=none,
  xmin=0,xmax=100,
  ymin=0,ymax=100,
  axis lines = middle,
  set layers,
  xlabel={$t$},ylabel={$T$},
  x label style={at={(1,0)},right},
  y label style={at={(0,1)},above},
  colormap={redblue}{rgb255(0cm)=(255,0,0); rgb255(1cm)=(0,0,255)}
               ]
    \draw [decorate,decoration={width and color change,
    start color=red,end color=blue}] (20,90) to[out=270,in=110] (25,60) to[out=335,in=115] (35,45) to[out=0,in=180] (70,45) to[out=305,in=150] (90,20);
    \node[inner sep=0pt, label={[outer sep=-2pt]45:A}] at (20,90) {} ;
    \node[label={[outer sep=-2pt]45:B}] at (25,60) {} ;
    \node[label={[outer sep=-2pt]45:C}] at (35,45) {} ;
    \node[label={[outer sep=-2pt]45:D}] at (70,45) {} ;
    \node[label={[outer sep=-2pt]45:E}] at (90,20) {} ;
    \addplot[only marks, mark options={solid,draw=green,fill=green}]
    coordinates {
    (20,90) (25,60) (35,45) (70,45) (90,20)
    };
    \end{axis}
\end{tikzpicture}
\end{figure}

\end{document}

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.