# How can I shift a background fading and shading in a TikZ picture?

Clearly all too naïvely, I would expect the following code

\documentclass[border=10pt,multi,tikz]{standalone}
\usetikzlibrary{fadings,backgrounds}
\pgfmathsetlengthmacro\hyd{sqrt(5)*.5*(145mm+2ex)}
\begin{tikzfadingfrompicture}[name=heulog]
\foreach \i [remember=\i as \j (initially 180), count=\k from 0] in {160,140,...,0}
\path [top color=transparent!100, bottom color=transparent!0, draw=transparent!100, line width=2.5pt, shading angle={-20*\k+80}] (0,0) -- ++(\j:\hyd) arc (\j:\i:\hyd) -- cycle;
\end{tikzfadingfrompicture}
\begin{document}
\begin{tikzpicture}
\path [ball color=magenta] (-.125*\hyd,0) -- (0,.25*\hyd) -- (.125*\hyd,0) -- (0,-.75*\hyd) -- cycle;
\begin{scope}[on background layer]
\coordinate [yshift=-1ex] (h) at (0,-.75*\hyd);
\begin{scope}[shift=(h)]
\path [scope fading=heulog, fit fading=false] (0,0);
\foreach \i [remember=\i as \j (initially 180)] in {160,140,...,0}
\path [fill=blue!50!cyan] (0,0) -- ++(\j:\hyd) arc (\j:\i:\hyd) -- cycle;
\end{scope}
\end{scope}
\end{tikzpicture}
\end{document}


to produce

In fact, however, the result is

In my real document, I cannot control the foreground drawing's absolute coordinates at all easily. For purposes of this question, therefore, assume that I cannot change

      \path [ball color=magenta] (-.125*\hyd,0) -- (0,.25*\hyd) -- (.125*\hyd,0) -- (0,-.75*\hyd) -- cycle;


How can I modify the code on the background layer and/or the definition of heulog to produce the expected output, without changing the code for the content on the main layer and without changing the order in which things are drawn?

I apologise for the slight complexity of the MWE. I had trouble breaking things satisfactorily with minimal code.

# EDIT 1

As pointed out in comments by Zarko, it is possible to adjust the fading so that it is correctly centred by scaling the tikzfadingfrompicture by 1.5. This would be problematic in practice because the right scalar will not always be easy to calculate. However, the main problem with scaling the fading in this way is similar to the problem with letting TikZ auto-scale it: the fading is severely diluted and does not give the effect of fading from full opacity to full transparency. That is, the output is

which is great, if that's what you want, but unfortunately not what I need here.

# EDIT 1a

It does matter that transparency is involved because it must work on a coloured background.

# EDIT 2

The following works, though I'm not sure why.

\begin{tikzpicture}
\path [ball color=magenta] (-.125*\hyd,0) -- (0,.25*\hyd) -- (.125*\hyd,0) -- (0,-.75*\hyd) -- cycle;
\begin{scope}[on background layer]
\path (0,-.75*\hyd) ++(0,-1ex) coordinate (h) (0,.25*\hyd) ++(0,1ex) coordinate (o);
\path (h);
\pgfgetlastxy{\hx}{\hy}
\path (o);
\pgfgetlastxy{\ox}{\oy}
\pgfmathsetmacro\hydy{(\hy+\oy)/2}
\pgfsetfading{heulog}{\pgftransformshift{\pgfpoint{0}{\hydy pt}}}
\begin{scope}[shift=(h)]
\foreach \i [remember=\i as \j (initially 180)] in {160,140,...,0}
\path [fill=blue!50!cyan] (0,0) -- ++(\j:\hyd) arc (\j:\i:\hyd) -- cycle;
\end{scope}
\end{scope}
\end{tikzpicture}


My theory was to adjust for the difference in distance between the top of the picture and the origin, on the one hand, and the bottom of the picture and the origin, on the other.

However, this fails in my real code. There, using

\pgfmathsetlengthmacro\hydy{(\hy+\oy)+1ex}%


seems to approximate the expected result. I can't give the full code for this as there's too much of it, but the immediate context is as follows, where staff is a local bounding box containing the stuff drawn in the foreground.

...
\path (staff.south) ++(0,-1ex) coordinate (h) (staff.north) ++(0,1ex) coordinate (o);
\path (h);
\pgfgetlastxy{\hx}{\hy}%
\path (o);
\pgfgetlastxy{\ox}{\oy}%
\pgfmathsetlengthmacro\hydy{(\hy+\oy)+1ex}%
\pgfsetfading{heulog}{\pgftransformshift{\pgfpoint{0}{\hydy}}}
\begin{scope}[shift=(h)]
% commenting the \pgfsetfading above and uncommenting this also works
%\path [scope fading=heulog, fading transform={shift={(0,\hydy)}}, fit fading=false] (0,0);
\foreach \i [remember=\i as \j (initially 180), count=\k from 0, evaluate=\k as \ll using \k*100/8] in {160,140,...,0}
\path [fill=Green4!\ll!Red3] (0,0) -- ++(\j:\hyd) arc (\j:\i:\hyd) -- cycle;
\end{scope}
...


but this makes no sense whatsoever. (At least, I'm assuming it makes sense to the brain of TikZ, but it makes none to the puny one with which nature equipped me!)

• @Zarko Unfortnuately, that does not work because it dilutes the effect of the fading. That is, it doesn't fade from fully opaque to fully transparent. (Also, in my real case, it would be difficult to calculate the equivalent of 1.5, but this is not so much of a problem in theory.)
– cfr
Sep 9 '16 at 23:45
• @Zarko Yes. I don't suppose the 1ex adjustment matters for the example. But scaling the fading is more problematic as it messes up the effect.
– cfr
Sep 9 '16 at 23:51
• @Zarko Please see edit. There are various ways of getting coverage, even with the rays starting from the base. But I can't get the full effect of the fading that way. Maybe the difficulty re-centring is a limitation of using pictures for fadings, but the manual doesn't say so. It doesn't like the asymmetry somehow.
– cfr
Sep 9 '16 at 23:58
• @Zarko Well, it is a picture fading and fit fading is set to false, so the size and scale will matter. But I'd expect to be able to centre the scope fading at an arbitrary point or shift it in a predictable manner. Yet I can't figure out how to do it.
– cfr
Sep 10 '16 at 0:40
• Did you try fading transform={shift={(current bounding box.center)}}? Sep 10 '16 at 6:43

## 1 Answer

You may transform (shift, rotate, etc.) your tikzfadingfrompicture via the fading transform key. Here, a solution may be:

fading transform={shift={(current bounding box.center)}}


(Note: ghostscript can't render correctly this document...)

The code:

\documentclass[border=10pt,multi,tikz]{standalone}
\usetikzlibrary{fadings,backgrounds}
\pgfmathsetlengthmacro\hyd{sqrt(5)*.5*(145mm+2ex)}
\begin{tikzfadingfrompicture}[name=heulog]
\foreach \i [remember=\i as \j (initially 180), count=\k from 0] in {160,140,...,0}
\path [top color=transparent!100, bottom color=transparent!0, draw=transparent!100, line width=2.5pt, shading angle={-20*\k+80}] (0,0) -- ++(\j:\hyd) arc (\j:\i:\hyd) -- cycle;
\end{tikzfadingfrompicture}
\begin{document}
\begin{tikzpicture}
\path [ball color=magenta] (-.125*\hyd,0) -- (0,.25*\hyd) -- (.125*\hyd,0) -- (0,-.75*\hyd) -- cycle;
\fill[red] circle(2pt);
\begin{scope}[on background layer]
\coordinate [yshift=-1ex] (h) at (0,-.75*\hyd);
\begin{scope}[shift=(h)]
\path
[scope fading=heulog, fit fading=false,
fading transform={shift={(current bounding box.center)}}]
(0,0);
\foreach \i [remember=\i as \j (initially 180)] in {160,140,...,0}
\path [fill=blue!50!cyan] (0,0) -- ++(\j:\hyd) arc (\j:\i:\hyd) -- cycle;
\end{scope}
\end{scope}
\end{tikzpicture}
\end{document}