5

I am annotating a picture with tikz.

I have tried

\documentclass[tikz]{standalone}

\usetikzlibrary{shapes,arrows,positioning,decorations.pathreplacing}

\begin{document}

\tikzset{%
    box/.style = {red, thick, rounded corners},
    arrow/.style = {->, green, ultra thick},
}

\begin{tikzpicture}[node distance=0.1cm, auto]
    % image
    \node[anchor=south west,inner sep=0] (image) at (0,0) {%
        \includegraphics[width=0.9\textwidth]{img/navbar.PNG}
    };

    % annotate
    \begin{scope}[x={(image.south east)},y={(image.north west)}]
        \draw[box] (0.02,0.15) rectangle (0.1,0.9);
        \node at (-0.02,-1) {Home};
        \draw[arrow] (0,-0.8) -- (0.02,0.15);
    \end{scope}
\end{tikzpicture}

\end{document}

My code works but I have manually placed my node with text "Home". I have to draw multiple boxes with text to each box. I also want an arrow from the text to the box to which the text belongs.

Can I use some positioning magic? I have tried naming the drawn rectangle with \draw[box] (home) (0.02,0.15) rectangle (0.1,0.9); but it's apparently not allowed to name rectangles like I can name nodes.

5

You can add a coordinate at one corner of the rectangle, draw a line with the end point relative to this with the ++(x,y) syntax, and add the Home node at the end of the line. Adjust the value for shorten < to your liking.

enter image description here

\documentclass[tikz,border=3mm]{standalone}

\usetikzlibrary{shapes,arrows,positioning,decorations.pathreplacing}

\begin{document}

\tikzset{%
    box/.style = {red, thick, rounded corners},
    arrow/.style = {->, green, ultra thick},
}

\begin{tikzpicture}[node distance=0.1cm, auto]
    % image
    \node[anchor=south west,inner sep=0] (image) at (0,0) {%
        \includegraphics[width=0.9\textwidth]{example-image}
    };

    % annotate
    \begin{scope}[x={(image.south east)},y={(image.north west)}]
        \draw[box] (0.02,0.15) coordinate(box1) rectangle (0.1,0.9);
        \draw [arrow,shorten <=1pt] (box1) -- ++(-0.1,-0.7) node[below,black]{Home};
    \end{scope}
\end{tikzpicture}

\end{document}
| improve this answer | |
  • Thank you. But sometimes I also want the annotation to be above the image and then it looks wrong when all the arrows are pointing to the lower left corner. Can I change that? – Jamgreen Jun 14 '15 at 14:13
  • @Jamgreen I don't really understand the problem. The end point of the arrow is defined by the coordinates in ++(-0.1,-0.7), change those and the arrow will point somewhere else. If it points upwards, you likely want to change the positioning of the node at the end of the arrow from below to above. – Torbjørn T. Jun 14 '15 at 14:17
2

Just for fun I created a macro to generate a node given its corners. This essentially gives you a box with anchor points.

\documentclass[tikz]{standalone}
\usepackage{mwe}% for example=image

\usetikzlibrary{shapes,arrows,positioning,decorations.pathreplacing,calc}

\newlength{\boxnodewidth}
\newlength{\boxnodeheight}

\newcommand{\boxnode}[4][\empty]% #1=parms (aptional), #2 = name, #3=SE corner x,y, #4=NW corner x,y
{\coordinate (boxnodecornerse) at (#3);
 \coordinate (boxnodecornernw) at (#4);
 \pgfextractx{\boxnodewidth}{\pgfpointdiff{\pgfpointanchor{boxnodecornerse}{center}}%
   {\pgfpointanchor{boxnodecornernw}{center}}}%
 \pgfextracty{\boxnodeheight}{\pgfpointdiff{\pgfpointanchor{boxnodecornerse}{center}}%
   {\pgfpointanchor{boxnodecornernw}{center}}}%
 \node[minimum width=\boxnodewidth,minimum height=\boxnodeheight,inner sep=0pt,#1] (#2) at ($(boxnodecornerse)!.5!(boxnodecornernw)$) {};
}

\begin{document}

\tikzset{%
    box/.style = {red, thick, rounded corners},
    arrow/.style = {->, green, ultra thick},
}

\begin{tikzpicture}[node distance=0.1cm, auto]
    % image
    \node[anchor=south west,inner sep=0] (image) at (0,0) {%
        \includegraphics[width=0.9\textwidth]{example-image}
    };

    % annotate
    \begin{scope}[x={(image.south east)},y={(image.north west)}]
        \boxnode[draw=red,rounded corners]{box}{0.02,0.15}{0.1,0.9}
        %\draw[box] (0.02,0.15) rectangle (0.1,0.9);
        \draw[arrow] (box.north) -- ++(0,1cm) node[black,above]{Home};
    \end{scope}
\end{tikzpicture}

\end{document}
| improve this answer | |
  • I have since discovered that a scope with [local bounding box=name] does the same thing. You can use \path to set the corners. OTOH, it will not work in [overlay] mode. – John Kormylo Dec 9 '17 at 17:05

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.