Layer between a node and its text

The old and  too localized solution where I defined an extra shape can be found in the history of this answer.


I can’t see a solution without re-using parts of the matrix.

Ideas:

  1. Drawing and filling the rectangle shape on a background layer, similar to Cut one side of a rectangle node in TikZ, didn’t work: Apparently \tikzlastnode (or \tikzmatrixname-\tikzmatrixcurrentrow-\tikzmatriccurrentcolumn) and pgfonlayer don’t play nice and mess within append after command.

    But, similar to solution 3, saving the draw and fill options for later use does work. Unfortunately, this deals differently with options that are given to every even row and the local |[<options>]| which is the reason why opacity=.5 and draw have to be given to the m-2-1 again, but this can be made easier with a style that is given to every even row and as well to the local options.

    The back style re-uses its argument (#1) with the option opacity=0; this serves the purpose of not changing the actual dimension of the nodes.

  2. Re-drawing the whole matrix where only the text is being typeset, realized be redefining PGF’s \pgfusepath or overwriting the fill and the draw style, so that one can just re-use the same \matrix call.

    This is the easiest solution, but re-draws the node’s content, therefore not usable when text opacity is applied.

  3. Saving the node’s text and typeset it again.

    • Unfortunatly, I couldn’t find a way to grab the node’s content and save it as plain text. (Reference: Using execute at begin node with \phantom and \pgfuseimage in TikZ?, Use node text as argument for a macro)

      Maybe there is a solution that uses a few named saveboxes and the lrbox environment.

    • That is the reason I defined a back style that takes the node’s content, typesets it inside a \phantom and saves it later with the node’s name to draw it on top of all (can be used inside a pgflayer, too, of course.

Code 1

\documentclass{beamer}

\usepackage{tikz,xparse,etoolbox,xstring}
\usetikzlibrary{matrix,backgrounds}

\definecolor{color3}{rgb}{0,1,0}\definecolor{color2}{rgb}{1,0,0}\definecolor{color1}{HTML}{999999}
\pgfdeclarelayer{myback}\pgfsetlayers{myback,background,main}

\tikzset{myfillcolor/.style = {draw=#1,fill=#1!50,rounded corners,line width=2pt}}
\NewDocumentCommand{\fhighlight}{O{color2} m m}{
    \draw[myfillcolor=#1] ([shift={(.1cm,-.1cm)}]#2.north west)rectangle ([shift={(-.1cm,.1cm)}]#3.south east);
}

\def\backgroundtodrawlater{}
\newcommand*{\saveMe}[1]{%
    \ifcsname iph\tikzmatrixname-\the\pgfmatrixcurrentrow-\the\pgfmatrixcurrentcolumn\endcsname
        \StrCount{\backgroundtodrawlater}{,}[\kommaCount]%
        \StrBefore[\kommaCount]{\backgroundtodrawlater}{,}[\backgroundtodrawlater]
    \fi
    \ifx\backgroundtodrawlater\empty%
        \xappto\backgroundtodrawlater{{#1}/\tikzmatrixname-\the\pgfmatrixcurrentrow-\the\pgfmatrixcurrentcolumn}%
    \else%
        \xappto\backgroundtodrawlater{,{#1}/\tikzmatrixname-\the\pgfmatrixcurrentrow-\the\pgfmatrixcurrentcolumn}%
    \fi%
    \expandafter\xdef\csname iph\tikzmatrixname-\the\pgfmatrixcurrentrow-\the\pgfmatrixcurrentcolumn\endcsname{}%
}
\newcommand*{\drawMyBackBoxes}{%
    \begin{pgfonlayer}{myback}
    \foreach \opt/\name in \backgroundtodrawlater {
        \expandafter\ifx\csname iph\name\endcsname\empty
%           \typeout{opt="\opt", name="\name"}% debug
            \expandafter\path\expandafter[\opt] (\name.south west) rectangle (\name.north east);
            \expandafter\xdef\csname iph\name\endcsname{ }
        \else
            \expandafter\xdef\csname iph\name\endcsname{}
        \fi
    }
    \end{pgfonlayer}
}
\tikzset{
    back/.style={
        #1,
        opacity=0,
        save path={#1},
    },
    save path/.code={\saveMe{#1}}
}
\begin{document}
\begin{frame}{Test frame}
\begin{tikzpicture}
\matrix [
    ampersand replacement=\&,
    matrix of nodes,
    nodes={inner sep=0pt,text centered,opacity=.5,text opacity=1},
    every even row/.style={nodes={
            rectangle,
            back={
                draw,
                fill=color1,
                opacity=.5
            },
            minimum size=0.8cm,
            font=\Large,
            text height=2ex,
            text depth=.25ex,
            text centered,
            text opacity=1,
    }},
    column 10/.style={nodes={text width=1cm}},
    row 1/.style={minimum height=0.5cm},
    row 5/.style={minimum height=0.5cm}
] (m) {
                                                  \& x \& x \&   \&   \\
        |[back={fill=color1!50, draw, dashed}]| ~ \& x \& x \& x \& x \\
        |[text height=0.2cm]|      ~                                  \\
        |[back={draw=none,fill=none}]| $x:$       \& x \& x \& x \& x \\
                                                  \& x \&   \&   \&   \\
    };

\begin{pgfonlayer}{background}
    \only<2>{\fhighlight[color2]{m-2-2}{m-4-5}}
    \only<3>{\fhighlight[color3]{m-2-1}{m-4-4}}
\end{pgfonlayer}

\drawMyBackBoxes
\end{tikzpicture}
\end{frame}
\end{document}

Code 2

\documentclass{beamer}
\usepackage{tikz,xparse}\usetikzlibrary{matrix,backgrounds}
\definecolor{color3}{rgb}{0,1,0}\definecolor{color2}{rgb}{1,0,0}\definecolor{color1}{HTML}{999999}
\tikzset{myfillcolor/.style = {draw=#1,fill=#1!50,rounded corners,line width=2pt}}
\NewDocumentCommand{\fhighlight}{O{color2} m m}{\draw[myfillcolor=#1] ([shift={(.1cm,-.1cm)}]#2.north west)rectangle ([shift={(-.1cm,.1cm)}]#3.south east);}
\newcommand{\repeatMeText}[1]{
    #1%
    \def\repeatMe{{% note the extra pair of braces, keeps changes local!
%       \renewcommand{\pgfusepath}[1]{}% either this
        \tikzset{
            fill/.style={},% or this and
            draw/.style={},% this
            column sep=\pgflinewidth,% compensates for missing "draw"
            row sep=.5\pgflinewidth% compensates for missing "draw"
            }
        #1
    }}
}
\begin{document}

\begin{frame}{Test frame}
\begin{tikzpicture}
\repeatMeText{
\matrix [
    ampersand replacement=\&,
    matrix of nodes,
    nodes={inner sep=0,text centered,opacity=.5,text opacity=1},
    every even row/.style={nodes={
            rectangle,
            draw,
            minimum size=0.8cm,
            fill=color1,
            font=\Large,
            text height=2ex,
            text depth=.25ex,
            text centered,
    }},
    column 10/.style={nodes={text width=1cm}},
    row 1/.style={minimum height=0.5cm},
    row 5/.style={minimum height=0.5cm}
] (m) {
                                     \& x \& x \&   \&   \\
        |[fill=color1!50, dashed]|~  \& x \& x \& x \& x \\
        |[text height=0.2cm]| ~                          \\
        |[draw=none,fill=none]| $x:$ \& x \& x \& x \& x \\
                                     \& x \&   \&   \&   \\
    };
}
\only<2>{\fhighlight[color2]{m-2-2}{m-4-5}}
\only<3>{\fhighlight[color3]{m-2-1}{m-4-4}}
\only<2,3>{\repeatMe}
\end{tikzpicture}
\end{frame}
\end{document}

Code 3

\documentclass{beamer}

\usepackage{tikz,xparse,etoolbox,xstring}
\usetikzlibrary{matrix,backgrounds}

\definecolor{color3}{rgb}{0,1,0}\definecolor{color2}{rgb}{1,0,0}\definecolor{color1}{HTML}{999999}
\pgfdeclarelayer{myback}\pgfsetlayers{myback,background,main}

\tikzset{myfillcolor/.style = {draw=#1,fill=#1!50,rounded corners,line width=2pt}}
\NewDocumentCommand{\fhighlight}{O{color2} m m}{
    \draw[myfillcolor=#1] ([shift={(.1cm,-.1cm)}]#2.north west)rectangle ([shift={(-.1cm,.1cm)}]#3.south east);
}

\def\backgroundtodrawlater{}
\newcommand*{\saveMe}[1]{%
    \ifcsname iph\tikzmatrixname-\the\pgfmatrixcurrentrow-\the\pgfmatrixcurrentcolumn\endcsname
        \StrCount{\backgroundtodrawlater}{,}[\kommaCount]%
        \StrBefore[\kommaCount]{\backgroundtodrawlater}{,}[\backgroundtodrawlater]
    \fi
    \ifx\backgroundtodrawlater\empty%
        \xappto\backgroundtodrawlater{{#1}/\tikzmatrixname-\the\pgfmatrixcurrentrow-\the\pgfmatrixcurrentcolumn}%
    \else%
        \xappto\backgroundtodrawlater{,{#1}/\tikzmatrixname-\the\pgfmatrixcurrentrow-\the\pgfmatrixcurrentcolumn}%
    \fi%
    \expandafter\xdef\csname iph\tikzmatrixname-\the\pgfmatrixcurrentrow-\the\pgfmatrixcurrentcolumn\endcsname{}%
}
\newcommand*{\drawMyBackBoxes}{%
    \begin{pgfonlayer}{myback}
    \foreach \opt/\name in \backgroundtodrawlater {
        \expandafter\ifx\csname iph\name\endcsname\empty
%           \typeout{opt="\opt", name="\name"}% debug
            \expandafter\path\expandafter[\opt] (\name.south west) rectangle (\name.north east);
            \expandafter\xdef\csname iph\name\endcsname{ }
        \else
            \expandafter\xdef\csname iph\name\endcsname{}
        \fi
    }
    \end{pgfonlayer}
}
\tikzset{
    back/.style={
        #1,
        opacity=0,
        save path={#1},
    },
    save path/.code={\saveMe{#1}}
}
\begin{document}
\begin{frame}{Test frame}
\begin{tikzpicture}
\matrix [
    ampersand replacement=\&,
    matrix of nodes,
    nodes={inner sep=0pt,text centered,opacity=.5,text opacity=1},
    every even row/.style={nodes={
            rectangle,
            back={
                draw,
                fill=color1,
                opacity=.5
            },
            minimum size=0.8cm,
            font=\Large,
            text height=2ex,
            text depth=.25ex,
            text centered,
            text opacity=1,
    }},
    column 10/.style={nodes={text width=1cm}},
    row 1/.style={minimum height=0.5cm},
    row 5/.style={minimum height=0.5cm}
] (m) {
                                                              \& x \& x \&   \&   \\
        |[back={fill=color1!50, draw, opacity=.5, dashed}]| ~ \& x \& x \& x \& x \\
        |[text height=0.2cm]|      ~                                              \\
        |[back={draw=none,fill=none}]| $x:$                   \& x \& x \& x \& x \\
                                                              \& x \&   \&   \&   \\
    };

\begin{pgfonlayer}{background}
    \only<2>{\fhighlight[color2]{m-2-2}{m-4-5}}
    \only<3>{\fhighlight[color3]{m-2-1}{m-4-4}}
\end{pgfonlayer}

\drawMyBackBoxes
\end{tikzpicture}
\end{frame}
\end{document}

Output 1

enter image description here

Output 2

enter image description here

Output 3

enter image description here


@Qrrbrbirlbel answer is very nice, but I think one could also proceed without saving the text. The trick is very simple: use at least three layers, myback, highlight and main; in the main layer there will be the text of the matrix, in the myback layer the matrix fill and in the highlight layer... the highlighting. What is important here, is that the highlight layer should be declared behind the main (text) but before the matrix fill (myback). Thus, with this approach, one should declare a posteriori how the matrix is filled and this is the only disadvantage I see.

The code:

\documentclass{beamer}
\usepackage{lmodern}
\usepackage{tikz,xparse}
\usetikzlibrary{matrix,backgrounds}

\definecolor{color3}{rgb}{0,1,0}
\definecolor{color2}{rgb}{1,0,0}
\definecolor{color1}{HTML}{999999}

\pgfdeclarelayer{myback} % layer to fill the matrix
\pgfdeclarelayer{highlight} % layer to highlight the matrix
\pgfsetlayers{myback,highlight,main}

\tikzset{my fill color/.style = {draw=#1,fill=#1!50,rounded corners,line width=2pt}}

\begin{document}

% For both commands the second argument could be used to select the layer: here
% is not really necessary since the default is required, but having this option may help
% for other purposes (I still have to think about them..)

\NewDocumentCommand{\fhighlight}{O{color2} O{highlight} m m}{
\begin{pgfonlayer}{#2}
\draw[my fill color=#1] ([shift={(.1cm,-.1cm)}]#3.north west)rectangle ([shift={(-.1cm,.1cm)}]#4.south east);
\end{pgfonlayer}
}

\NewDocumentCommand{\bhighlight}{O{black} O{myback} m m}{
\begin{pgfonlayer}{#2}
\draw[#1] (#3.north west)rectangle (#4.south east);
\end{pgfonlayer}
}

\begin{frame}{Test frame}
\begin{tikzpicture}
\matrix [
    ampersand replacement=\&,
    matrix of nodes,
    nodes={inner sep=0,text centered},
    every even row/.style={nodes={
                minimum size=0.8cm,
                %fill=color1,
                font=\Large,
                text height=2ex,
                text depth=.25ex,
                text centered,
                }},
        column 10/.style={nodes={text width=1cm}},
        row 1/.style={minimum height=0.5cm},
        row 5/.style={minimum height=0.5cm}
    ] (m) {
    \& x\& x\&\&\\
    ~\&x\&x\&x\&x\\
    |[text height=0.2cm]|~\\
   $x:$\&x\&x\&x\&x\\
    \& x\&\&\&\\
    };

% the matrix fill always visible: put in last layer, myback

\bhighlight[fill=color1!50, dashed, opacity=0.5]{m-2-1}{m-2-1}

\foreach \i in {2,...,5}{
\pgfmathtruncatemacro\x{\i}
\bhighlight[draw,rectangle, opacity=0.5]{m-2-\x}{m-2-\x}
}

\foreach \i in {2,...,5}{
\pgfmathtruncatemacro\x{\i}
\bhighlight[draw,rectangle, opacity=0.5]{m-4-\x}{m-4-\x}
}

% matrix highlighting

\only<2>{\fhighlight[color2]{m-2-2}{m-4-5}}
\only<3>{\fhighlight[color3]{m-2-1}{m-4-4}}
\end{tikzpicture}
\end{frame}

\end{document}

The result:

enter image description here