5

I have different elements (say, a node and a filled circle) defined using a single path:

\path (0,0)
    node [blue] {some text}
    [fill, red] circle [radius = 1];

Issue: I would like to put one of these elements (the circle) on a given layer (that is the background layer).

I have tried [fill, red, on background layer] as option but it doesn't work. I cannot open/close a scope environment in the middle of a path neither.


MWE

The example below is constructed as following:

  1. some elements (here a black line),
  2. a path containing a node with text and a circle.

Resulting layers are thus (considering first bullet = top layer) :

  • text + circle,
  • some elements.

However, I'd like to have:

  • text,
  • some elements,
  • circle.

enter image description here

\documentclass[margin=10pt]{standalone}
    \usepackage{tikz}
        \usetikzlibrary{positioning, fadings, backgrounds}
\begin{document}
    \begin{tikzpicture}
            \draw [very thick] (-1,-1) -- (1,1);
            \path (0,0)
                node [red!20, font=\sffamily\bfseries] {some text}
                [fill, red, on background layer] circle [radius=1];

            \node at (0,2) {actual trial};

        \begin{scope}[xshift=-3cm]
            \path (0,0) [fill, red, on background layer] circle [radius = 1];
            \draw [very thick] (-1,-1) -- (1,1);
            \path (0,0) node [red!20, font=\sffamily\bfseries] {some text};

            \node at (0,2) {expected};
        \end{scope}
    \end{tikzpicture}
\end{document}

Edit:

For a better understanding, here is my real problem that is abstracted hereinabove. In following picture, I want the text to be above the axes (as it is now), and the shading below (it is not the case)... and I want to draw both of them using on unique command.

enter image description here

  • 1
    Take a look at the last version of my answer at tex.stackexchange.com/a/20426/86 – Loop Space Jul 27 '16 at 16:28
  • @LoopSpace I'd forgotten about your code in that answer. (I've never used it, but I've seen it.) That is definitely the way to go if the OP really needs this. Though I've not seen evidence yet that there aren't simpler solutions to the problem this question is really trying to solve! – cfr Jul 27 '16 at 17:14
  • @cfr the picture now in the post would seem to require it, though I agree that there might be simpler ways to achieve the same end (particularly as that is one of my ... more hackish ... answers). – Loop Space Jul 27 '16 at 18:32
  • @LoopSpace : many thanks, I've written an answer based on your suggestion! – ebosi Jul 28 '16 at 15:38
4

You could try with a pic. It's possible to define foreground code and background code which are drawn in front or behind the path.

enter image description here

enter image description here

\documentclass[margin=10pt]{standalone}
    \usepackage{tikz}
        \usetikzlibrary{positioning, fadings, backgrounds}

\tikzset{
    pics/mypic/.style = {
        foreground code = {\node [red!20, font=\sffamily\bfseries]{sometext};},
        background code = {\draw[fill, red] circle [radius=1];}
        }
}       

\begin{document}
    \begin{tikzpicture}
       \draw [very thick] (-1,-1) -- pic{mypic} (1,1);
   \end{tikzpicture}

   \begin{tikzpicture}
       \draw [very thick] (-2,0) -- (2,0) (0,-2)--(0,2) (.5,.5) pic{mypic};
   \end{tikzpicture}
\end{document}
  • I really like the pic approach, since it is exlpicit and intuitive. However, it suppose to draw every thing at the same time (in my case, the axes at the same time than the faded area). But what I'd like to achieve is: (1) defining axes, and other stuff (2) create with 1 command both the text (foreground) and the faded area (background) with one path/command. In your code, it works, but only because axes are defined at the same time than the "bubble". So it's a solution, but not optimal for me -- even I do appreciate the effort you gave for answering! – ebosi Jul 28 '16 at 14:36
  • @ebo Then I think you can try with Loop Space on layer solution. He suggested after I posted my answer and after not carefully reading it I think it solves your problem. – Ignasi Jul 28 '16 at 14:43
  • Yup, it's what I'm doing (and also trying to adapt Alenanno's answer) (-; – ebosi Jul 28 '16 at 14:46
4

You can use the decorations.markingslibrary, along with the preaction key, so that the decoration is added "before" the path is drawn. Basically this is like the second solution you posted, but all in one.

This code provides a style with two arguments decred={ <pos> }{ <text> }. The colored node will be behind the line, the text in front of it.

Output

enter image description here

Code

\documentclass[margin=10pt]{standalone}
\usepackage{tikz}

\usetikzlibrary{decorations.markings, backgrounds}

\tikzset{
    decred/.style 2 args={%
        decoration={markings, mark = at position #1 with {
            \begin{scope}[on background layer]
            \node[fill=red, circle, font=\sffamily\bfseries] {\phantom{#2}};
            \end{scope}
            \node[circle, text=red!20, font=\sffamily\bfseries] {#2};
        }}, postaction={decorate},
        thick,
    }
}

\begin{document}
\begin{tikzpicture}
\draw[decred={.5}{some text}] (-1,-1) -- (1,1);
\end{tikzpicture}
\end{document}
  • Thank you for helping. I'm sorry, but I think my question was not explicit enough: what I'd like to have is the black line in between the circle (backgroung) and the text (forground) (as in a sandwich)... while defining the circle and the text in a same path. The black line is here just a random element representing the 'middle-ground' – ebosi Jul 27 '16 at 14:45
  • 1
    @ebo See new edit. – Alenanno Jul 27 '16 at 18:10
1

Here is a solution, based on LoopSpace's suggestion and on his work for implementing Z levels (i.e. layers) in TikZ.

The tricky part of the initial problem is the following: an object can be easily send to the background using [on background layer] option of the backgrounds TikZ-library. However, this apply to the whole path.

Yet, in my question, I wanted one part of a single path to be put on foreground, and another on the background.

Hence, the trick is to use several backgrounds (cf. LoopSpace work) and to apply them with pre/postactions. (Here, the text is first written with the [on layer=top] option, and then, using a postaction, we switch to the background and fill the circle).

The benefit of this solution compared to the other, is that you can put as many elements as you want in the middle ground (here symbolized with the black rule).
Furthermore, the "text+circle" element is independent of those middle-ground elements. Moreover, giving only one coordinate for the whole path, you have one of its component (text) on foreground, and one other on background (circle).

enter image description here

\documentclass[margin=10pt]{standalone}
    \usepackage{tikz}
        \usetikzlibrary{positioning, fadings, backgrounds}

    %-- see tex.stackexchange.com/a/20426/86    
    \pgfdeclarelayer{back}
    \pgfdeclarelayer{front}
    \pgfsetlayers{back,main,front}

    \makeatletter
    \pgfkeys{%
        /tikz/on layer/.code={
            \pgfonlayer{#1}\begingroup
            \aftergroup\endpgfonlayer
            \aftergroup\endgroup
        },
        /tikz/node on layer/.code={
            \gdef\node@@on@layer{%
                \setbox\tikz@tempbox=\hbox\bgroup\pgfonlayer{#1}\unhbox\tikz@tempbox\endpgfonlayer\egroup}
            \aftergroup\node@on@layer
        },
        /tikz/end node on layer/.code={
            \endpgfonlayer\endgroup\endgroup
        }
    }

    \def\node@on@layer{\aftergroup\node@@on@layer}

    \makeatother
  %-- end see, many thanks to LoopSpace

\begin{document}
    \begin{tikzpicture}
            \node at (0,2) {solution};

            \draw [very thick] (-1,-1) -- (1,1);
            \path (0,0)
                [postaction={on layer = back, fill, red}] % <=== here is the trick: for the postaction, another layer is selected, and instructions are given for drawing the circle.
                node [%
                    red!20, font=\sffamily\bfseries,%
                    on layer = front % <==== It puts the text on foreground
                ] {some text}
                [radius = 1] circle % <==== note that the circle is defined, but without any information about "how to draw it"
            ;


        \node at (4.5,2) {not working};
        \draw (3,1.8) -- +(3, 0);
        \begin{scope}[xshift=3cm]
            \draw [very thick] (-1,-1) -- (1,1);
            \path (0,0)
                [postaction={on background layer, fill, red}] % <=== here is the trick: for the postaction, another layer is selected, and instructions are given for drawing the circle.
                node [%
                    red!20, font=\sffamily\bfseries,%
                    %on layer = front % <==== It puts the text on foreground
                ] {some text}
                [radius = 1] circle % <==== note that the circle is defined, but without any information about "how to draw it"
            ;
        \end{scope}

        \begin{scope}[xshift=6cm]
            \draw [very thick] (-1,-1) -- (1,1);
            \path (0,0)
                node [on layer = front, red!20, font=\sffamily\bfseries] {some text} % <== here the layer is set to front, but...
                [on layer = back, fill, red, radius = 1] circle % <== there, we set the layer to back, and this apply *to the whole* path!
            ;
        \end{scope}
    \end{tikzpicture}
\end{document}

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.