Conditional tikz Node Fill

A simple approach using the key/val interface:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{positioning,shapes}

\newcommand{\mycommand}[2][]{
    \begin{tikzpicture}[
        draw=gray,
        baseline=-0.5ex,
        every node/.style={
            draw,
            signal, signal to=east,
            minimum height=.9em, minimum width=2mm
          },
        progress/.style={segment ##1/.style={fill}},
        progress/.list={#2},
        #1,
    ]

    \node[segment 1/.try] (1) {};
    \node[signal from=west, right=0pt of 1,segment 2/.try] (2) {};
    \node[signal from=west, right=0pt of 2,segment 3/.try] (3)  {};
    \node[signal from=west, right=0pt of 3,segment 4/.try] (4) {};
    \node[signal from=west, signal to=0, right=0pt of 4,segment 5/.try] (5) {};
    \end{tikzpicture}
}

\newcommand{\myprogress}[2][]{\mycommand[#1]{0,...,#2}}

\begin{document}
    \mycommand{}\par
    \mycommand{1,...,5}\par
    \mycommand[fill=red]{1,3,5}\par
    \mycommand[draw=blue]{2,...,5}\par
    \mycommand{4}\par
    \myprogress{4}\par
\end{document}

The \mycommand macro allows you to provide a list of segments to fill, the \myprogress one to just fill them up to the number provided. The optional argument is a regular tikz key/val list, so you can customize the colors very naturally by setting fill=color or draw=color.

preview

Explanation

The idea is to have a key segment N for each of the segments 1 to 5. Then the key is empty if there is nothing to do for that segment, or set to fill if the segment needs to be filled. So the nodes style now contain segment N but I added /.try so that TikZ simply ignores the key if it is not defined. This way we do not have to give trivial definitions for these keys when they should have no effect.

Now we want to set the segment N keys in a simple way, i.e. with a list syntax. First we provide a helper key progress=N that has the effect of setting segment N to fill. Then we use the utility /.list to execute the progress=K key for each item K of the list provided as argument (#2). Finally, we execute #1 as a key/val list so that keys in the optional argument can overwrite the current scope.

One final touch: we set the draw color outside of the every node style so that it is set for the whole pic as a default, the every node style now just requires the draw action without specifying a color, so that the actual color can be overwritten by the #1 argument if needed.

Generalisation

If you want to make the definition of the macro a little bit less ad-hoc, you can generalise it to N segments (here N is the first mandatory argument), and use chains to position the segments.

Note: I set node distance to -\pgflinewidth so that the borders are not doubled in width at the segment boundaries.

\usetikzlibrary{chains}

\newcommand{\mycommand}[3][]{
    \begin{tikzpicture}[
        draw=gray,
        baseline=-0.5ex,
        every node/.style={
            draw,
            signal, signal to=east,
            minimum height=.9em, minimum width=2mm
          },
        progress/.style={segment ##1/.style={fill}},
        progress/.list={#3},
        start chain,
        node distance = -\pgflinewidth,
        #1,
    ]

    \node[on chain,segment 1/.try] {};
    \ifnum#2>2
    \pgfmathsetmacro{\N}{#2-1}
    \foreach \K in {2,...,\N}{
        \node[on chain,signal from=west, segment \K/.try] {};
    }
    \fi
    \node[on chain,signal from=west, signal to=0,segment #2/.try] {};
    \end{tikzpicture}
}

preview2


enter image description here

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{positioning,shapes}

\begin{document}
\newcommand\zz[1]{%
\begin{tikzpicture}[baseline=-0.5ex]
    \tikzstyle{every node}=[signal, signal to=east, draw=gray, minimum height=.9em, minimum width=2mm];
    \node[fill=\ifnum#1>0 black\else white\fi] (1) {};
    \node[fill=\ifnum#1>1 black\else white\fi,signal from=west, right=0pt of 1] (2) {};
    \node[fill=\ifnum#1>2 black\else white\fi,signal from=west, right=0pt of 2] (3)  {};
    \node[fill=\ifnum#1>3 black\else white\fi,signal from=west, right=0pt of 3] (4) {};
    \node[fill=\ifnum#1>4 black\else white\fi,signal from=west, signal to=0, right=0pt of 4] (5) {};
\end{tikzpicture}}

\zz{0}

\zz{1}

\zz{2}

\zz{3}

\zz{4}

\zz{5}

\end{document}

And yet another proposal....

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{positioning,shapes,calc}
\newcounter{instances} % introduced to avoid giving two different nodes the same name
\newcommand{\mycommand}[1]{\stepcounter{instances}
    \ifnum#1=0
    \node (\theinstances-1) {};
    \else
    \node[fill=black] (\theinstances-1) {};
    \fi
    \foreach \i in {1,...,4}
    {
    \pgfmathtruncatemacro{\j}{\i+1}
    \pgfmathtruncatemacro{\k}{min(-\i+#1,1)*100}
    \node[signal from=west, right=0pt of \theinstances-\i,fill=black!\k!white]
    (\theinstances-\j) {};
    }
}   

\begin{document}
\begin{tikzpicture}[baseline=-0.5ex]
    \tikzstyle{every node}=[signal, signal to=east, draw=gray, minimum height=.9em, minimum width=2mm];
    \foreach \f in {0,...,5}
    {\begin{scope}[yshift=-\f cm]
    \mycommand{\f}
    \end{scope}}
\end{tikzpicture}
\end{document}

enter image description here

Tags:

Nodes

Tikz Pgf