8

I draw some blocks with below code:

\documentclass{article}

\usepackage{tikz}
\usepackage{pgfplots}

\begin{document}
\begin{figure}[h!]
    \centering
    \resizebox{\textwidth}{!}{%
    \begin{tikzpicture}[text centered]
        \foreach \x in {-8, -7.4, -6.8, -6.2}
        \foreach \y in {1.8, 1.2, ..., -2.4}
            \draw (\x,\y) rectangle (\x+0.5,\y+0.5);

    \end{tikzpicture}
    }%
\end{figure}
\end{document}

I can fill different color to each of them when I draw them one by one, but how can I fill after I draw them with this batch? For example, I only want to fill some of them with red like picture shows below. (can I named each block as a node and I can fill by selecting the node name?)

enter image description here

6

You can name the coordinates and then color it (using a background layer) after the fact.

\documentclass{article}

\usepackage{tikz}

\begin{document}
\begin{figure}[h!]
    \centering
    \resizebox{\textwidth}{!}{%
        \begin{tikzpicture}[text centered]
            % use layers to add shading "under" the rectangles
            \pgfdeclarelayer{background}
            \pgfsetlayers{background,main}
            \foreach[count=\ordx from 1] \x in {-8, -7.4, -6.8, -6.2}
            \foreach[count=\ordy from 1] \y in {1.8, 1.2, ..., -2.4}
            % name the top left and bottom right coordinate
            \draw (\x,\y) coordinate(TL-\ordx-\ordy) rectangle (\x+0.5,\y+0.5) coordinate(BR-\ordx-\ordy);
            % go on the background layer
            \begin{pgfonlayer}{background}
                % you can use your coordinates here; lot of possibilities
                % if you add the calc tikzlibrary
                \fill[red!20]  (TL-1-1) rectangle (BR-1-1);
                \fill[green!20]  (TL-3-1) rectangle (BR-3-1);
                \fill[red!70]  (TL-4-4) rectangle (BR-4-4);
            \end{pgfonlayer}
        \end{tikzpicture}
    }%
\end{figure}
\end{document}

The trick here is that you name the top left coordinate with (TL-x-y) y the corresponding bottom right (BR-x-y), and then use them to add the filling in the background layer.

Notice that the node names are valid only in the same tikzpicture, unless you use the option remember picture (but then you have to take care of things like stretching and resizing, which is not trivial to manage)

enter image description here

7

You can use a matrix

\documentclass[tikz]{standalone}
\usetikzlibrary{matrix}
\begin{document}
\begin{tikzpicture}[]
\matrix[matrix of nodes,nodes in empty cells,row sep=1mm,column sep=1mm,
    nodes={minimum size=0.5cm,draw,anchor=center,outer sep=0},
    row 5 column 2/.style={nodes={fill=blue}},
    column 1/.style={nodes={fill=red!50}},
    row 3 column 1/.style={nodes={shade,right color=yellow}}
]{&&&\\&&&\\&&&\\&&&\\&&&\\&&&\\&&&\\};
\end{tikzpicture}
\end{document}

enter image description here

  • The nodes inside a matrix are also automatically named. – percusse Dec 25 '17 at 15:45
5

One way (pretty verbose) is to expand two loops into a single one, but loop over three variables (the coordinates and color):

\documentclass{article}
\usepackage{tikz}
\usepackage{pgfplots}
\begin{document}
\begin{figure}[h!]
    \centering
    \resizebox{\textwidth}{!}{%
    \begin{tikzpicture}[text centered]
        \foreach \i / \j / \c in
          {0/6/red,   1/6/white, 2/6/white, 3/6/white,
           0/5/white, 1/5/white, 2/5/white, 3/5/white,
           0/4/white, 1/4/white, 2/4/white, 3/4/white,
           0/3/white, 1/3/white, 2/3/red,   3/3/white,
           0/2/white, 1/2/white, 2/2/white, 3/2/white,
           0/1/white, 1/1/red,   2/1/white, 3/1/red,
           0/0/white, 1/0/white, 2/0/white, 3/0/white}
           \filldraw[fill=\c] (-8+0.6*\i,1.8+0.6*\j) rectangle (-7.5+0.6*\i,1.3+0.6*\j);
    \end{tikzpicture}
    }%
\end{figure}
\end{document}

enter image description here

Or you can store the properties into a separate file (you can generate it programmatically), and do the following (the idea is taken from Reading the data to iterate over with \foreach from a file):

\begin{filecontents*}{\jobname.dat}
0/6/red,   1/6/white, 2/6/white, 3/6/white,
0/5/white, 1/5/white, 2/5/white, 3/5/white,
0/4/white, 1/4/white, 2/4/white, 3/4/white,
0/3/white, 1/3/white, 2/3/red,   3/3/white,
0/2/white, 1/2/white, 2/2/white, 3/2/white,
0/1/white, 1/1/red,   2/1/white, 3/1/red,
0/0/white, 1/0/white, 2/0/white, 3/0/white
\end{filecontents*}
\documentclass{article}
\usepackage{tikz}
\usepackage{pgfplots}
\usepackage{catchfile}
\newcommand\loaddata[1]{\CatchFileDef\loadeddata{#1}{\endlinechar=-1}}
\begin{document}
\begin{figure}[h!]
    \centering
    \resizebox{\textwidth}{!}{%
    \begin{tikzpicture}[text centered]
        \loaddata{\jobname.dat}
        \foreach \i / \j / \c in \loadeddata
           \filldraw[fill=\c] (-8+0.6*\i,1.8+0.6*\j) rectangle (-7.5+0.6*\i,1.3+0.6*\j);
    \end{tikzpicture}
    }%
\end{figure}
\end{document}

The file \jobname.dat is included into the main file for convenience only.

  • that means if I need draw hundreds of blocks, then I need write down each property of them like 0/6/red? – How Chen Dec 25 '17 at 9:28
  • That means that this solution wouldn't be a good one for the case of hundreds of blocks. I'd recommend to create the property list in a CSV file and use it in tikz picture. – Sergei Golovan Dec 25 '17 at 9:30

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.