11

How to colorized any line drawed with draw (nor with plot expression)? enter image description here

\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=1.18}
\begin{document}

\begin{tikzpicture}
\begin{axis}[
    axis lines = middle,
    %title={Cor baseada no valor de $y$},
    title={Color depending on $y$ coordinate},
    colormap/hot % Podes usar 'hot', 'cool', 'jet', etc.
]
    \addplot[
    mesh,                % Divide o trazo en segmentos para aplicar cores
    thick,
    domain=-3:3,
    samples=100,
    point meta=y         % Indica que a cor depende do valor de y
    ] 
    {x^2};                   % A función matemática    
    
    \draw[thick, xshift=0.5,rounded corners] (-2,0.5) .. controls (0,-1) and (0,7) .. (1,7.8) .. controls (2,1) and (2,4) .. (3,3) node[anchor=east,pos=0.95] {How to colorize black line with colormap?} node[anchor=north east,pos=0.95] {depending on $y$ coordinate};
\end{axis}
\end{tikzpicture}

\end{document} 
3
  • 2
    Please extend your code snippet to a compilable MWE. Thank you Commented 2 days ago
  • 3
    @JasperHabicht Thank you, excuse me, I thought I posted a mwe but... 3 initial lines was not copied. Commented 2 days ago
  • maybe partly related: tex.stackexchange.com/questions/141378/… Commented 2 days ago

5 Answers 5

6

Here is a proposal with luadraw (which produces TikZ) using g:Dshadedpolyline():

\documentclass{standalone}%compile with lualatex only
\usepackage[svgnames]{xcolor}
\usepackage{luadraw}%https://github.com/pfradin/luadraw/
\usepackage{fourier-otf}
%Source - https://tex.stackexchange.com/q/761483
\begin{document}
\begin{luadraw}{name=test}
local g = graph:new{window={-3,3,-1,9}, size={12,12,0} }
require 'luadraw_shadedforms'
local f = function(x) return x^2 end
g:Daxes()
local L = cartesian(f,-3,3)
g:Dshadedpolyline(L,palRainbow,{values="y",width=8})
local C = {Z(-2,0.5), Z(0,-1), Z(0,7), Z(1,7.8), "b", Z(2,1), Z(2,4), Z(3,3),"b"}
-- the path(C) instruction transforms the path C into a polygonal line.
g:Dshadedpolyline(path(C),palRainbow,{values="y",width=8})
g:Show()
\end{luadraw}
\end{document}

enter image description here

2
  • Excellent luadraw_shadedforms module since luadraw v2.5! Commented 2 days ago
  • @Explorer Thank you ! Commented 2 days ago
6

As far as I know, this cannot be done directly with an ordinary \draw command.

The reason is that colormap in pgfplots works via point meta, and to color a line segment by segment, you need \addplot[mesh,...]; an ordinary TikZ path has no such mechanism.

So the practical approach is not to draw the curve as \draw ... .. controls ..., but to represent it as a parametric curve using \addplot and set point meta=y. Here is an example of how this can be done:

\documentclass[border=25pt]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.18}

\begin{document}
\begin{tikzpicture}
\begin{axis}[
    axis lines=middle,
    title={Color depending on $y$ coordinate},
    colormap/hot,
]

% обычный график
\addplot[
    mesh,
    ultra thick,
    domain=-3:3,
    samples=100,
    point meta=y
] {x^2};

% first cubic Bézier segment
\addplot[
    mesh,
    ultra thick,
    point meta=y,
    variable=\t,
    domain=0:1,
    samples=80,
] (
    {
      -2*(1-\t)^3 + \t^3
    },
    {
      0.5*(1-\t)^3
      - 3*(1-\t)^2*\t
      + 21*(1-\t)*\t^2
      + 7.8*\t^3
    }
);

% second cubic Bézier segment
\addplot[
    mesh,
    ultra thick,
    point meta=y,
    variable=\t,
    domain=0:1,
    samples=80,
] (
    {
      1*(1-\t)^3
      + 6*(1-\t)^2*\t
      + 6*(1-\t)*\t^2
      + 3*\t^3
    },
    {
      7.8*(1-\t)^3
      + 3*(1-\t)^2*\t
      + 12*(1-\t)*\t^2
      + 3*\t^3
    }
);

\node[anchor=east] at (axis cs:3,3.5)
  {How to colorize black line with colormap?};
\node[anchor=east] at (axis cs:3,3.0)
  {depending on $y$ coordinate};

\end{axis}
\end{tikzpicture}
\end{document}

enter image description here

6

For comparison, here is an approach using Metapost. I'm showing two different palettes: standard HSV colours and one of the colour ranges defined in Colorbrewer. In both cases I am "cheating" by drawing the line as a series of dots (but this is essentially what all the other tools are doing, they just hide it from the user).

function plot with spectral colouring

You need to compile this with lualatex. Follow the link at the top for tutorials and reference material about Metapost.

\documentclass[border=5mm]{standalone}
\usepackage{luamplib}
\begin{document}
\mplibtextextlabel{enable}
\begin{mplibcode}
vardef hsv_color(expr h, s, v) =
  save chroma, hh, x, m;
  chroma = v * s;
  hh = h / 60;
  x  = chroma * (1 - abs(hh mod 2 - 1));
  m  = v - chroma;
  if     hh < 1: (chroma,x,0)+(m,m,m)
  elseif hh < 2: (x,chroma,0)+(m,m,m)
  elseif hh < 3: (0,chroma,x)+(m,m,m)
  elseif hh < 4: (0,x,chroma)+(m,m,m)
  elseif hh < 5: (x,0,chroma)+(m,m,m)
  else:          (chroma,0,x)+(m,m,m)
  fi
enddef;
beginfig(1);
  numeric u, v;
  u = 2v = 25;

  path xx, yy;
  xx = (left--right) scaled 3u;
  yy = origin -- up scaled 9v;

  numeric s; s = 1/8;
  path ff;
  ff = (-3,9) for x = s-3 step s until 3: -- (x, x*x) endfor;
  ff := ff xscaled u yscaled v;

  for t = 0 step 1/8 until arclength ff:
    pair w; w = point arctime t of ff of ff;
    draw w withcolor hsv_color(30(9 - ypart w / v),2,1); 
  endfor

  path gg;
  gg = (-2,0.5) .. controls (0,-1) and (0,7) .. (1,7.8) .. controls (2,1) and (2,4) .. (3,3);
  gg := gg xscaled u yscaled v;

  input colorbrewer-rgb
  for t = 0 step 1/8 until arclength gg:
    pair w; w = point arctime t of gg of gg;
    numeric p, q; 
    p = 8 - ypart w / v;
    q = floor p; 
    draw w withcolor (p-q)[PiYG[9][q+1], PiYG[9][q+2]];
  endfor

  ahangle := 20;
  drawoptions(withcolor 1/2);
    drawdblarrow xx scaled 1.2;
    drawarrow yy scaled 1.1;
    for x = -3,-2,-1,1,2,3: 
      draw (down--up) scaled 2 shifted (x*u,0);
      label.bot("$" & decimal x & "$", (x*u, -2));
    endfor
    for y = 2, 4, 6, 8:
      draw (left--right) scaled 2 shifted (0, y*v);
      label.lft("$" & decimal y & "$", (-2, y*v));
    endfor
  drawoptions();
endfig;
\end{mplibcode}
\end{document}
6

A draw can only have one color. As you show, you can use the option mesh to split the path into multiple colored segments. -this is the "correct" methode. If you really insist on a draw instead of a plot, it can actually be done with a tikzfadingfrompicture although I can not recommend this methode:

\documentclass[tikz, border=1cm]{standalone}
\usetikzlibrary{fadings}
\usepackage{pgfplots}
\pgfplotsset{compat=1.18}
\usepgfplotslibrary{patchplots}

\begin{tikzfadingfrompicture}[name=myfading]
\begin{axis}[axis lines=middle, draw=none, xmin=-3, xmax=3, ymin=0, ymax=9]
\draw[transparent!0, thick, xshift=0.5, rounded corners] (-2,0.5) .. controls (0,-1) and (0,7) .. (1,7.8) .. controls (2,1) and (2,4) .. (3,3);
\end{axis}
\path (0,0) circle[radius=10]; %encompassing circle for alignment
\end{tikzfadingfrompicture}

\begin{document}
\begin{tikzpicture}
\begin{axis}[
axis lines=middle, xmin=-3, xmax=3, ymin=0, ymax=9,
colormap/hot,
]
\addplot[mesh, thick, domain=-3:3, samples=100, point meta=y] {x^2};
\path[scope fading=myfading, fit fading=false] (0,0);
\addplot[patch, shader=interp, patch type=rectangle, patch refines=3] coordinates{(-3,0) (-3,9) (3,9) (3,0)};
\end{axis}
\end{tikzpicture}
\end{document} 

Graph with two color shaded curves

5

Here is another apporach, using masking group technique provided by luamplib package. The code is based on Truston's answer above, but the lines are real lines, not thousands of dots with different colors. As for colors, I chose the closest colors in my eyes, as I do not have information about colormaps.

Of course, it needs to compile with lualatex.

\documentclass[border=5mm]{standalone}
\usepackage{luamplib}
\begin{document}
\mplibtextextlabel{enable}
\mpfig*
  numeric u, v;
  u = 2v = 25;

  path xx, yy;
  xx = (left--right) scaled 3u;
  yy = origin -- up scaled 9v;

  path ff;
  ff = origin .. controls (1/3, 0) and (2/3, 1/3) .. (1,1);
  ff := reverse ff reflectedabout (down, up) & ff;
  ff := ff xscaled 3u yscaled 9v;

  path gg;
  gg = (-2,0.5) .. controls (0,-1) and (0,7) .. (1,7.8) .. controls (2,1) and (2,4) .. (3,3);
  gg := gg xscaled u yscaled v;

  picture bgbox;
  bgbox = image(
    save bboxmargin; bboxmargin := 1/2;
    fill bbox ff
      withshadingmethod "linear"
      withshadingvector (0,3)
      withshadingstep (
        withshadingfraction 1/3
        withshadingcolors (blue, (1,1,0))
      )
      withshadingstep (
        withshadingfraction 3/3
        withshadingcolors ((1,1,0), red)
      )
  );
\endmpfig

\mplibgroup{linesmask}[asgroup="masking"]
  \mpfig
    pickup pencircle scaled 1;
    draw ff withcolor 1;
    draw gg withcolor 1;
  \endmpfig
\endmplibgroup

\mpfig
  draw bgbox withmaskinggroup "linesmask";

  ahangle := 20;
  drawoptions(withcolor 1/2);
  drawdblarrow xx scaled 1.2;
  drawarrow yy scaled 1.1;
  for x = -3,-2,-1,1,2,3:
    draw (down--up) scaled 2 shifted (x*u,0);
    label.bot("$" & decimal x & "$", (x*u, -2));
  endfor
  for y = 2, 4, 6, 8:
    draw (left--right) scaled 2 shifted (0, y*v);
    label.lft("$" & decimal y & "$", (-2, y*v));
  endfor
  drawoptions();
\endmpfig
\end{document}

lines coloring with masking group

1
  • The new features being added to luamplib are very good to see. Commented 2 days ago

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.