17

I want to mark various places on a graphic. I would like to use callouts as there are easy to shift around, but I would prefer an arrow instead of the standard tip. Has someone seen some code for this or want to write it?

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{shapes.callouts}
\usetikzlibrary{decorations.text}
\usetikzlibrary{positioning}
\begin{document}
\tikzset{markplace/.style=
 {rectangle callout,
  fill=orange,
  callout absolute pointer={#1},
  at={#1},
  above=1cm  
  }}

\begin{tikzpicture}
\draw[fill,green] (1,1) circle (1pt);

\node[markplace={(1,1)}] {here};

\node[markplace={(1,1)},below left=2cm and 0.5cm] {and here};

\end{tikzpicture}
\end{document}

enter image description here

Edit

I now came up with this code (I will naturally write some wrapper code but haven't decided about the syntax yet): It finds the location of the callout without drawing it. Then draws the arrow from the center, and then the rectangle on top of it.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{shapes.callouts}
\usetikzlibrary{decorations.text}
\usetikzlibrary{positioning}

\begin{document}
\tikzset{markplace/.style=
 {rectangle callout,
  fill=none,draw=none,
  callout absolute pointer={#1},  
  at={#1},
  above=1cm
  }}


\begin{tikzpicture}
\draw[fill,green] (1,1) circle (1pt);

\tikzset{shorten >=1pt}

\node[markplace={(1,1)}] (B) {here};
  \draw[-latex,thick,orange] (B.center)--(1,1);
\node[anchor=center,at=(B.center),fill=orange,rectangle]{here};


\node[markplace={(1,1)},below left=2cm and 0.5cm] (B) {and here};
  \draw[-latex,thick,orange] (B.center)--(1,1);
\node[anchor=center,at=(B.center),fill=orange,rectangle]{and here};


\node[markplace={(0,1)},above left=-1cm and 3cm] (B) {blub};
  \draw[-latex,thick, red] (B.center)--(1,1);
\node[anchor=center,at=(B.center),fill=orange,rectangle]{blub};


\end{tikzpicture}
\end{document}

enter image description here

  • What should define the arrowhead size ? Or should it always saturate at a certain size? – percusse Nov 21 '13 at 19:33
  • @percusse At best they should behave like normal arrows and usevthenormal options - as if one had used an arrow path with node at the end (the current code uses arrows + nodes but the angles and the connections are not satisfying, so I want to switch to callouts) – Ulrike Fischer Nov 21 '13 at 20:19
  • A customised pin wouldn't do the job? Or is this what you meant by "(the current code uses arrows + nodes but the angles and the connections are not satisfying, so I want to switch to callouts)"? – cjorssen Nov 21 '13 at 20:57
  • @cjorssen: No I don't think that pin would meet my needs: the callout shape does some sophisticated calculation to decide about the angle of the tip. E.g. even if I use in the example above anchor=south east,above left=2cm and 2cm the pointer don't start at the edge of the rectangle. I will edit my question to show the code I got until now and the result I want to get. – Ulrike Fischer Nov 22 '13 at 9:19
  • Aargh, I misread it. I thought you want arrow tips at the end of the variable thickness lines... Sorry. – percusse Nov 22 '13 at 12:45
8

This I think does it. I "simply" hack the background path for the rectangle callout shape and insert some conditional code to allow a tikz path for the callout pointer.

Note, that the path is drawn from the center of the shape, so if it is not filled it will look ugly (if it was drawn from the border of the shape there may be a gap between the shape and the start of the line).

\documentclass[border=0.125cm]{standalone}
\usepackage{tikz}
\usetikzlibrary{shapes.callouts}
\usetikzlibrary{positioning}

\newif\iftikzcalloutarrow

% Ooo this is naughty...
%
\def\hack#1\fi\fi#2\endhack{%
 \expandafter\def\csname pgf@sh@bg@rectangle callout\endcsname{%
    #1\fi\fi%
    \iftikzcalloutarrow
      % New pointer code
        \pgfscope\path[rectangle callout arrow options/.try] 
          \pgfextra{\pgfpathmoveto{\centerpoint}\pgfpathlineto{\calloutpointer}};
        \endpgfscope%
        \pgfpathmoveto{\beforecalloutpointer}%
        \pgfpathlineto{\aftercalloutpointer}%
        {%
            \pgftransformshift{\centerpoint}%
            \pgfpathlineto{\firstpoint}\pgfpathlineto{\secondpoint}%
            \pgfpathlineto{\thirdpoint}\pgfpathlineto{\fourthpoint}%
            \pgfpathclose%
        }%
    \else%
    #2
    \fi}%
}
\expandafter\expandafter\expandafter\hack\csname pgf@sh@bg@rectangle callout\endcsname\endhack

\tikzset{%
    markplace/.style={%
        rectangle callout,
    fill=orange,text=black,
    callout absolute pointer={#1},
    at={#1},
    above=1cm  
  }, 
  rectangle callout arrow/.code={%
    \tikzcalloutarrowtrue%
    \tikzset{rectangle callout arrow options/.style={#1}}%
  }
}


\begin{document}


\begin{tikzpicture}

\draw[fill,green] (1,1) circle [radius=1pt];
\node[markplace={(1,1)}] {here};
\node[markplace={(1,1)}, rectangle callout arrow={draw=orange, -stealth},
  below left=2cm and 0.5cm] {and here};

\node[markplace={(1,1)}, rectangle callout arrow={draw=black, -latex, dashed},
  below right=1cm and 0.5cm] {and also here};
\end{tikzpicture}

\end{document}

enter image description here

  • In a document of my own this would be fine. But I don't think I should redefine an internal command like \csname pgf@sh@bg@rectangle callout\endcsname in document I want to give to someone. – Ulrike Fischer Nov 22 '13 at 16:00

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.