11

Let's take the following picture as an example. I want to shade the fan-shaped area from red to green along the curve shown with the arrow in TikZ. How can I do this?

enter image description here

Code:

\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}[scale = 5]
    \draw [->] (180:.2cm) -- (0:2.2cm);
    \draw [->] (-90:.2cm) -- (90:2.2cm);

    \filldraw [red, draw = black] (0:0cm) -- (0:2cm) arc(0:30:2cm) -- cycle;
    \filldraw [green, draw = black] (0:0cm) -- (60:2cm) arc(60:90:2cm) -- cycle;

    \draw (30:2cm) arc(30:60:2cm);
    \draw [->] (30:1cm) arc(30:60:1cm);
    \node at (45:1cm) {need shade here};
\end{tikzpicture}
\end{document}

Update

What I mean by "along a curve" is a little hard to understand, so I'll try to explain it:

  • Pick a point from that curve;
  • Pick the tangent to the point on the curve;
  • The color of every points on the line that is perpendicular to the tangent are the same.

Update 2

Inspired by Harish Kumar, I think we can split the very area to small fan-shaped areas, say SFSA, and define a command who could return tangential every reference points on the curve. If we have that command, we will be able to fill each SFSA with proper color and proper shading angle.

Any hints or clues?

14

A solution with a PDF shading. Problems start if you want to do this more flexible (with different angles) as there is no proper way to change the shading dependent of other values besides colors. (I tried using colors to smuggle in values but that failed already at Is there another better way to have a region with gradient opacity?)

The second example shows a simple TikZ approach by filling thirty separate slices. This is no true shading but my be enough if you need multiple different shadings. You can, of course, use more slices for better results or less slices for a faster compilation.

The actual formula for the start and end angle is:

\i*<total angle>/<number of slices>+30

and

(\i+1)*<total angle>/<number of slices>

The formula for \col is simply

\col=(\i+.5)/<number of slices>*100

Code

\documentclass[tikz]{standalone}
\usetikzlibrary{shadings}
\makeatletter
\pgfdeclarefunctionalshading[col@ang@start,col@ang@end]{angular 30:60}
  {\pgfpointorigin}{\pgfpoint{50bp}{50bp}}{%
    \pgfshadecolortorgb{col@ang@start}\pgf@col@ang@start
    \pgfshadecolortorgb{col@ang@end}\pgf@col@ang@end}
  {exch atan 30 sub 30 div dup dup
  dup \pgf@col@ang@startred   mul exch neg 1 add \pgf@col@ang@endred   mul add
  3 1 roll
  dup \pgf@col@ang@startgreen mul exch neg 1 add \pgf@col@ang@endgreen mul add
  3 1 roll
  dup \pgf@col@ang@startblue  mul exch neg 1 add \pgf@col@ang@endblue  mul add}
\pgfset{
  angular start color/.code=\pgfutil@colorlet{col@ang@start}{#1},
  angular end color/.code=\pgfutil@colorlet{col@ang@end}{#1},
  angular start color=red,
  angular end color=green}
\makeatother
\begin{document}
\begin{tikzpicture}[scale = 5, radius=2cm, delta angle=30]
    \draw [->] (180:.2cm) -- (0:2.2cm);
    \draw [->] (-90:.2cm) -- (90:2.2cm);

    \filldraw [red,   draw = black] (0:0cm) -- ( 0:2cm) arc[start angle=0]  -- cycle;
    \filldraw [green, draw = black] (0:0cm) -- (60:2cm) arc[start angle=60] -- cycle;

    \filldraw[line join=bevel, shading=angular 30:60]
                                    (0:0cm) -- (30:2cm) arc[start angle=30] -- cycle;
\end{tikzpicture}
\begin{tikzpicture}[scale = 5, radius=2cm, delta angle=30]
    \draw [->] (180:.2cm) -- (0:2.2cm);
    \draw [->] (-90:.2cm) -- (90:2.2cm);

    \filldraw [red,   draw = black] (0:0cm) -- ( 0:2cm) arc[start angle=0]  -- cycle;
    \filldraw [green, draw = black] (0:0cm) -- (60:2cm) arc[start angle=60] -- cycle;

    \foreach \i[evaluate={\col=(\i+.5)/30*100}] in {0,...,29}
      \fill[color=green!\col!red]
             (0,0) -- (\i+30:2cm) arc[start angle=\i+30, end angle=\i+1+30] -- cycle;
    \draw[line join=bevel]          (0:0cm) -- (30:2cm) arc[start angle=30] -- cycle;
\end{tikzpicture}
\end{document}

Output

enter image description hereenter image description here

Update

The code for the second picture can be made a bit more flexible:

\def\subdivisions{30}
\begin{tikzpicture}[scale = 5, radius=2cm, delta angle=30]

  \draw [->] (180:.2cm) -- (0:2.2cm);
  \draw [->] (-90:.2cm) -- (90:2.2cm);
  \filldraw [red,   draw = black] (0:0cm) -- ( 0:2cm) arc[start angle=0]  -- cycle;
  \filldraw [green, draw = black] (0:0cm) -- (60:2cm) arc[start angle=60] -- cycle;

  \foreach \i[evaluate={\col=(\i+0.5)/\subdivisions*100}] in {0,...,\numexpr\subdivisions-1\relax}
    \fill[color=green!\col!red] (0,0) -- (\i*30/\subdivisions+30:2cm) arc[start angle=\i*30/\subdivisions+30, end angle=(\i+1)*30/\subdivisions+30] -- cycle;
  \draw[line join=bevel]      (0:0cm) -- (30:2cm) arc[start angle=30] -- cycle;
\end{tikzpicture}
  • I have updated your answer; I hope it is okay. – Svend Tveskæg Dec 1 '13 at 23:14
5

Here radial shading is used to shade the sector area. fadings library from tikz is required.

enter image description here

Code

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{fadings}
\begin{document}
\begin{tikzpicture}[scale = 5]
    \draw [->] (180:.2cm) -- (0:2.2cm);
    \draw [->] (-90:.2cm) -- (90:2.2cm);

    \filldraw [red, draw = black] (0:0cm) -- (0:2cm) arc(0:30:2cm) -- cycle;
    \path [shading=radial, top color=green,  bottom color=red]  (0,0) --  (30:2cm) arc (30:60:2cm)  --(0,0);   % modify this line for next image below.
    \filldraw [green, draw = black] (0:0cm) -- (60:2cm) arc(60:90:2cm) -- cycle;

    \draw (30:2cm) arc(30:60:2cm);
    \draw [->] (30:1cm) arc(30:60:1cm);
    \node at (45:1cm) {need shade here};
\end{tikzpicture}
\end{document}

Update: Checking the tikz/pgf manual, there are 3 predefined shadings: axis, radial, and ball. Obviously, radial and ball are not desired. So I tried axis with shading angle=45(30+60/2) and the result is similar to Harish Kumar's result. All I did was to change the path command to the following command.

\path [top color=green,  bottom color=red, shading=axis, shading angle=45]  (0,0)  --  (30:2cm) arc (30:60:2cm)  -- (0,0);

and the result is shown below.

enter image description here

  • Sorry, this is not I want. top color=green, bottom color=red is wrong, however, maybe end arrow color = green, start arrow color = red is right (just for instance, not working) and this is what I mean `alone a curve'. Thank you all the same. – Ch'en Meng Dec 1 '13 at 13:26
  • @Ch'enMeng -- still trying here, to meet your wish. – Jesse Dec 1 '13 at 13:30
  • I updated my question. I hope that is helpful to you. :) – Ch'en Meng Dec 1 '13 at 13:37
  • Why `at' isn't working... – Ch'en Meng Dec 1 '13 at 13:37
4

This is not an exact answer to your question. Actually you have to define a proper angular shading and use it for an exact effect. But for the time being this is what I can add.

\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}[scale = 5]
    \draw [->] (180:.2cm) -- (0:2.2cm);
    \draw [->] (-90:.2cm) -- (90:2.2cm);

    \filldraw [red, draw = black] (0:0cm) -- (0:2cm) arc(0:30:2cm) -- cycle;
    \filldraw [green, draw = black] (0:0cm) -- (60:2cm) arc(60:90:2cm) -- cycle;    
    \filldraw[top color=green, bottom color=red,shading=axis,shading angle=50,]
  (0,0) -- (30:2cm) arc(30:60:2cm) -- cycle;

    %\draw (30:2cm) arc(30:60:2cm);
%    \draw [->] (30:1cm) arc(30:60:1cm);
%    \node at (45:1cm) {need shade here};
\end{tikzpicture}
\end{document}

enter image description here

  • How about splitting the fan-shaped area to many small parts, say SFSA (small fan-shaped area), and then fill each of them by a proper shading angle? Gradually changing the angle while gradually changing the color? – Ch'en Meng Dec 1 '13 at 14:05
  • I don't know why but I get a black slice in the middle if I copy-paste your code. – Alenanno Jun 4 '15 at 9:53

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.