2

I'm trying to shade (transition from one color to another color) between two concentric objects with happen to be rectangles, while producing multiple concentric objects in a \foreach loop.

I can produce the multiple concentric objects using \node and using \draw. Using draw, I can shade the outer object using \shadedraw, and \fill the inner object using fill=white. Unfortunately, the shading goes from the center, but I want the shading to go from the boundary of the inner object. I want the shading to transition from inner (red) to outer (blue)

Any suggestion on using draw, shadedraw, or node?

Here's my Minimal Working Example using pdflatex, and the output is below.

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{shapes.geometric}

\begin{document}

\begin{center}
\begin{tikzpicture}
        \def\x{7.5}
        \def\z{0.25}
        \pgfmathsetmacro{\xx}{6.5-2*\z}
        \pgfmathsetmacro{\yy}{5.0-2*\z}
        \foreach \y in {0, 1}  {
        \node[draw, rectangle, rounded corners=5ex, blue!40, minimum width=6.5 cm, minimum height=5 cm] (rect01) at (3.25+\y*\x,2.5) {};
        \node[draw, rectangle, rounded corners=4ex, red!40, minimum width=\xx cm, minimum height=\yy cm] (rect01) at (3.25+\y*\x,2.5) {};
        }
\end{tikzpicture}
\end{center}

\begin{center}
\begin{tikzpicture}
        \def\x{7.5}
        \def\z{0.25}
        \pgfmathsetmacro{\xx}{6.5-2*\z}
        \pgfmathsetmacro{\yy}{5.0-2*\z}
        \foreach \y in {0, 1}  {
        \shadedraw[inner color=red!40, outer color=blue!40, draw=blue!40, rounded corners=5ex] (\y*\x, 0.0) rectangle (6.5+\y*\x, 10.0);
        \draw[red!40, fill=white, rounded corners=4ex] (\y*\x+2*\z, 0.0+2*\z) rectangle (6.5+\y*\x-2*\z, 10.0-2*\z);
        }
\end{tikzpicture}
\end{center}

\end{document}

enter image description here

EDIT BELOW is in response to Black Mild's very nice suggestion of combining \fill with a couple of \defs.

\fill has two features with are incompatible with the situation I stated. One feature I can work around, the other feature I cannot.

  • The fading by \fill is radially symmetric: cannot work around this feature.

  • \fill also fades from the center of the concentric shapes to the edge of the larger shape: can work around this by adjusting the color transparency.

Essentially, \fill will paint the entire area of the larger figure, and do so with radial symmetry from the center of the figure. Defining the paths separately is a nice procedure for radially symmetric shapes, but not for rectangles.

See the figure below for the effect on rectangles and the work around for adjusting color transparency.

Solution_using_fill

  1. \def\incurve{(2,-3) circle(0.5)} \def\outcurve{(2,-3) circle(2)} \fill[inner color=red!40, outer color=blue!40,even odd rule] \incurve \outcurve;
  2. \def\incurveTwo{(7,-3) circle(1.5)} \def\outcurveTwo{(7,-3) circle(2)} \fill[inner color=red!40, outer color=blue!40,even odd rule] \incurveTwo \outcurveTwo;
  3. \def\incurveThree{(12,-3) circle(1.75)} \def\outcurveThree{(12,-3) circle(2)} \fill[inner color=red!80, outer color=blue!20,even odd rule] \incurveThree \outcurveThree;

1 Answer 1

3

Here is a suggestion for you, using fill only.

enter image description here

\documentclass[tikz,border=5mm]{standalone}
\begin{document}
\begin{tikzpicture}
\def\incurve{(0,0) circle(1)}
\def\outcurve{(0,0) circle(2)}
\fill[inner color=red!40, outer color=blue!40,even odd rule] \incurve \outcurve;
\draw[red] \incurve; 
\draw[blue] \outcurve;
\end{tikzpicture}
\end{document}

There is a cheat that works in this case only: draw many circles with suitable colors and radii.

enter image description here

\documentclass[border=5mm]{standalone}
\usepackage{tikz}
\usepackage{asymptote}
\begin{document}
\begin{tikzpicture} 
\def\incurve{(0,0) circle(1)} 
\def\outcurve{(0,0) circle(2)} 
\foreach \i in {1,2,...,100} 
\draw[blue!\i!red] (0,0) circle(1+.01*\i); 
\draw[red] \incurve; 
\draw[blue] \outcurve; 
\end{tikzpicture}
\end{document}

Note that evenodd rule in Asymptote works very well for this kind of filling. Resulting picture is almost identical to the above "cheat" one.

enter image description here

% asy.exe -f pdf -noView "xxx".asy
% by Le Quoc Hiep  
unitsize(1cm);
real r1=1, r2=2;
path incurve=scale(r1)*unitcircle;
path outcurve=scale(r2)*unitcircle;
radialshade(incurve^^outcurve,red+evenodd,(0,0),r1,blue,(0,0),r2);
shipout(bbox(5mm,Fill(white)));
6
  • 1
    Thanks for the suggestion using \fill. It works for circles in your example, but not rectangles, the shape I specified in my question. Also, there's some work around needed because \fill fades from the center as I showed in my edit to the question. Thanks anyways, though. Jan 22, 2020 at 12:33
  • @DavidCollins an interesting question! let us try more
    – Black Mild
    Jan 22, 2020 at 15:23
  • 1
    @DavidCollins How about this cheat? \begin{tikzpicture} \def\incurve{(0,0) circle(1)} \def\outcurve{(0,0) circle(2)} \foreach \i in {1,2,...,100} \draw[blue!\i!red] (0,0) circle(1+.01*\i); \draw[red] \incurve; \draw[blue] \outcurve; \end{tikzpicture}
    – Black Mild
    Jan 22, 2020 at 16:29
  • Thanks! That almost got me there. Nice solution nonetheless. I needed to use\pgfmathsetmacro{\ii}{{5-\i/100} to handle the rounded corners. This fix worked well for solid colors: blue to red. However, for blue!40 to red!40, another set of \pgfmathsetmacro{\ii}{40-\i/100*40} & \pgfmathsetmacro{\jj}{\i/100*40}was needed. The interaction between \pgfmathsetmacro and rounded corners was fine. However, the interaction between \pgfmathsetmacro and 'blue!\ii!\i\!red!\jj` or even 'blue!\i\!red!\jj` was not. Jan 27, 2020 at 8:39
  • 1
    I accepted to answer since it largely took care of the issue I presented. I figured that final touch is the source for another question once I work out a MWE. Maybe I'll even get it solved while creating the MWE. But until then there is far more work to do creating this climate change board game. Thanks Again!! Jan 27, 2020 at 8:43

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .