[Tex/LaTex] Periodic shading in tikz

shadingtikz-pgf

Is there an easy way to shade a rectangle in tikz so that the color changes not from one to the other but several times in between. Something like a grayscale value changing with the position x like cos(x).

A linear variation instead of a sinusoidal one would be fine: I'd jsut like it to mimic an interference pattern.

Best Answer

You could try shadings:

\documentclass[tikz,border=5]{standalone}
\begin{document}
\tikz[x=0.125cm,y=0.125cm]
  \foreach \i in {0,1,...,21}
    \path [left color=black, right color=white, shading angle={mod(\i,20)*180+90}]
    (\i*.9,0) rectangle ++(1,10);
\end{document}

enter image description here

Or fadings:

\documentclass[tikz,border=5]{standalone}
\usetikzlibrary{fadings}
\begin{tikzfadingfrompicture}[name=interference]
\foreach \i in {0,1,...,21}
    \path [left color=transparent!0, right color=transparent!100, shading angle={mod(\i,2)*180+90}]
    (\i*.9,0) rectangle ++(1,20);
\end{tikzfadingfrompicture}
\begin{document}
\foreach \i in {0,...,24}{
\begin{tikzpicture}
\clip (-5,-5) rectangle ++(10,10);
\path [fill=black, path fading=interference, fit fading=false, fading transform={rotate=\i*7.2}] (-10,-5]) rectangle ++(20,10);
\path [fill=black, path fading=interference, fit fading=false] (-10,-5) rectangle ++(20,10);
\end{tikzpicture}
}
\end{document}

enter image description here

In both cases using \i*.9 is to workaround some annoying white lines that appear between adjacent shadings which may (or may not) be viewer artifacts.

To change the phase of the interference pattern is tricky to do with shading but with fadings it is fairly easy if the fading is specified over a larger area than the required path. Then the fading transform key can be used to shift the fading that is "seen through" the path.

In the following example the red rectangle illustrates the position of the fading relative to the area that is faded. Also, a line is drawn to fill in the white lines between adjacent shadings instead of the workaround described above to get rid of the white lines that appear between adjacent shadings.

\documentclass[tikz,border=5]{standalone}
\usetikzlibrary{fadings}
\begin{tikzfadingfrompicture}[name=interference]
\foreach \i in {0,1,...,19}{
  \path [left color=transparent!0, right color=transparent!100, shading angle={mod(\i,2)*180+90}]
  (\i,0) rectangle ++(1,10);
  \ifodd\i\else% Fill in gap
    \path [draw=transparent!0] (\i,0) -- ++(0,10);
  \fi
}
\end{tikzfadingfrompicture}
\begin{document}
\foreach \i in {-10,...,10,9,8,...,-9}{%
\begin{tikzpicture}
\path [draw=red, shift=(0:\i/2)] (-10,-5) rectangle (10,5);
\path [fill=black, path fading=interference, fit fading=false, fading transform={shift=(0:\i/2)}] (-5,-5) rectangle (5,5);
\useasboundingbox (-15,-5) rectangle (15,5);
\end{tikzpicture}%
}
\end{document}

enter image description here

Using fadings means you can also do cool stuff like this:

\documentclass[tikz,border=5]{standalone}
\usetikzlibrary{fadings}
\begin{tikzfadingfrompicture}[name=interference]
\foreach \i in {1,...,15}
    \foreach \j in {1,...,25}
       \path [line width=\j, draw=transparent!0,opacity=1/30]
    (0:\i) arc (0:180:\i);
\end{tikzfadingfrompicture}
\begin{document}
\begin{tikzpicture}
\clip (-5,-5) rectangle ++(10,10);
\path [fill=black, path fading=interference, fit fading=false] (-10,-5) rectangle ++(20,10);
\path [fill=black, path fading=interference, fit fading=false, fading transform={rotate=45}] (-10,-5) rectangle ++(20,10);
\end{tikzpicture}

\end{document}

enter image description here