7

In the reply to this question on shadows, it was suggested to use the backgrounds library so that the shadow of one object doesn't overlap another object drawn previously.

If I understand the documentation correctly, I have to pass on background layer as an option to the scope, not to the path. On the other hand, a preaction constructs a scope internally (according to the docs).

Is it possible to change the options for the scope that is constructed internally by preaction? How? If not, an enhancement to TikZ would solve the "overlapping shadows" problem in an elegant way.

krlmlr
  • 12,530

1 Answers1

7

Much to my surprise, the solution from the question "Z-level" in TikZ seems to work with preactions and postactions. Here's a fairly simple example.

\documentclass{article}
%\url{https://tex.stackexchange.com/q/46957/86}

\usepackage{tikz}
\pgfdeclarelayer{back}
\pgfsetlayers{back,main}

\makeatletter
\pgfkeys{%
  /tikz/on layer/.code={
    \pgfonlayer{#1}\begingroup
    \aftergroup\endpgfonlayer
    \aftergroup\endgroup
  },
  /tikz/node on layer/.code={
    \pgfonlayer{#1}\begingroup
    \expandafter\def\expandafter\tikz@node@finish\expandafter{\expandafter\endgroup\expandafter\endpgfonlayer\tikz@node@finish}%
  },
}

\begin{document}
\begin{tikzpicture}
\draw[line width=1cm,red] (2,1) -- (2,-1);
\draw[ultra thick,white,preaction={on layer=back,line width=1cm,blue,draw}] (0,0) -- (4,0);
\draw[line width=1cm,red] (2,-2) -- (2,-4);
\draw[ultra thick,white,postaction={on layer=back,line width=1cm,blue,draw}] (0,-3) -- (4,-3);
\begin{scope}[xshift=5cm]
\draw[line width=1cm,red] (2,1) -- (2,-1);
\draw[ultra thick,white,preaction={line width=1cm,blue,draw}] (0,0) -- (4,0);
\draw[line width=1cm,red] (2,-2) -- (2,-4);
\draw[ultra thick,white,postaction={line width=1cm,blue,draw}] (0,-3) -- (4,-3);
\end{scope}
\end{tikzpicture}
\end{document}

Result:

TikZ pre- and post-actions with z-level

The left-hand pictures have the layer set for the blue line, the right do not. The upper have the blue line drawn as a preaction, the lower as a postaction. In each, the vertical red line is drawn before the horizontal lines. So for the upper two, the order of specifying is: red, blue, white. For the lower two, the order is: red, white, blue (coincidence, I assure you). With the "on layer" set, the order of rendering is: blue, red, white. This shows that the blue line (the action line) is sent to the back by the on layer=back key.

Andrew Stacey
  • 153,724
  • 43
  • 389
  • 751
  • Amazing! Apart from the missing \makeatother, could you please also provide an example for node on layer? – krlmlr Mar 06 '12 at 19:14
  • Yes, I spotted that before looking at your other question but not in time for this one! I'll add the example for node on layer to the original question as it fits better there. – Andrew Stacey Mar 06 '12 at 19:30
  • Aagh. node on layer is no longer working for me. A workaround is \path[on layer=back] node .... – Andrew Stacey Mar 06 '12 at 20:17
  • Perhaps some PGF internals have changed? More than half a year has passed since you answered the other question... Is \node[node on layer=back] still the correct syntax? – krlmlr Mar 06 '12 at 20:31
  • @user946850 See original question: I've fixed the node on layer code. – Andrew Stacey Mar 07 '12 at 19:25