72

I have two arrows going from a node on the left to a node on the right. Both arrows are slightly bent. I want to label the arrows with text that is bent just like the arrows. This is as far as I've got:

\begin{tikzpicture}
\node (One) at (-3,0) [shape=circle,draw] {One}; 
\node (Two) at (3,0) [shape=circle,draw] {Two};
\draw [->, thick] (One) to [bend right=45]  (Two);
\draw [->, thick] (One) to  [bend left=45] (Two);
\node (mental) at (0,1.75) {Some bent text};
\node (non-mental) at (0,-1.75) {Some more bent text};
\end{tikzpicture}
Martin Scharrer
  • 262,582
Speldosa
  • 5,077
  • 5
  • 31
  • 40
  • You want the node text to be bent? I'm not sure that's easy... – Seamus Jul 04 '11 at 17:00
  • Sorry, I was a bit unclear there. I don't really care what it is that gets bent. I just want bent text as the end result. My first try was to do this with nodes. – Speldosa Jul 04 '11 at 17:19
  • 3
    Note that for straight node labels you normally attach the node to the path and not place it manually: \draw [->, thick] (One) to [bend right=45] (Two) node [midway] {some text}; – Martin Scharrer Jul 04 '11 at 17:43
  • how to specify same decoration to all paths, like in tikz environment –  Mar 10 '12 at 14:13
  • 1
    @gangadhar You'll have better luck asking a new question than using an answer to ask a question. – Alan Munn Mar 10 '12 at 16:05
  • @gangadhar Welcome to TeX.SE. As AlanMunn says, please post a new question - link to this if needed. Also, it would be very helpful to to compose a fully compilable MWE that illustrates the problem including the \documentclass and the appropriate packages so that those trying to help don't have to recreate it, and instead can focus on the specific question at hand. – Peter Grill Mar 10 '12 at 17:08

3 Answers3

76

This can be done by the decorations.text library gives you a text along path decoration. See the PGF/TikZ manual (v2.10) on page 337, section 30.6 Text decorations for more details. You can't draw and decorate the path at the same time directly, but can use postaction={..} to decorate the path after you have drawn it (Thanks goes to Alan Munn for this tip).

To format the text place the style macros between | in the text argument. Non-English characters need to be included in braces, e.g. text={|\itshape|Some Text {ö} more text}. One issue is to raise the font (it is just placed really on the path!). I looked into the source code and found out that the font macros are placed before each single processed character but with an \relax between it, i.e. <your style>\relax<character>. You could define a macro which takes two arguments, the first is the \relax and the second the character, then use \raisebox{<length>}{<content>} to raise or lower the character.

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{decorations.text}

\begin{document}

\begin{tikzpicture}
\node (One) at (-3,0) [shape=circle,draw] {$One$}; 
\node (Two) at (3,0) [shape=circle,draw] {$Two$};
\def\myshift#1{\raisebox{-2.5ex}}
\draw [->,thick,postaction={decorate,decoration={text along path,text align=center,text={|\sffamily\myshift|Some more bent text}}}] (One) to [bend right=45]  (Two);
\def\myshift#1{\raisebox{1ex}}
\draw [->,thick,postaction={decorate,decoration={text along path,text align=center,text={|\sffamily\myshift|Some bent text}}}]      (One) to [bend left=45] (Two);
\end{tikzpicture}

\end{document}

Image

Martin Scharrer
  • 262,582
  • I was just about to post this solution too, but I was unable to figure out how to move the text so that (i) it doesn't overlap the line so much and (ii) have the lower text wrap under the line (without being upside-down.) Do you know how to do that? BTW, you can also add the decoration as a postaction to the \draw command instead of having both the \path and \draw commands. – Alan Munn Jul 04 '11 at 17:37
  • @Alan: postaction is a good idea. I'm currently also look for a technique how to move the text. – Martin Scharrer Jul 04 '11 at 17:46
  • This is great. However, I also want to do exactly the things that Alan Munn suggests. – Speldosa Jul 04 '11 at 18:21
  • 1
    You could shift the coordinates for the text path with ($(One)+(0,1)$) for example (needs calc library). I don’t know why yshift=1cm doesn’t work. Maybe because you don’t use absolute coordinates. – Tobi Jul 04 '11 at 18:55
  • @Tobi: (One) to (Two) gives quit different results than when both are shifted. In the first case the border of both are are used and in the second case the center is shifted and then used. Also note that you can use yshift inside the coordniate spec: ([yshift=1cm]One), which also doesn't work well enough. – Martin Scharrer Jul 04 '11 at 18:59
  • That's great. There's only one problem left for me now. I'm trying to change the font by putting in "font=\sffamily" on different places (I've declared it as a parameter for the TikZ environment but it seems to be overridden by "decoration.text") but I can't get it to change. – Speldosa Jul 04 '11 at 19:29
  • @Martin: Ahh … I didn’t know that. But there must be a way to shift the whole path as it is (I hope …) – Tobi Jul 04 '11 at 19:38
  • 1
    @Speldosa: font is only used for nodes AFAIK. Styles can be given between delimiters which are set using text format delimiters={<start>}{<begin>}, by default both are |, so use text={|\somefontcommands|your text}. – Martin Scharrer Jul 04 '11 at 19:39
  • 2
    @Speldosa: I think you’ll have to aply the font directly to the path’s text, like text={|\sffamily| Some Text}; please see page 337 an 338 of the pgfmanual. EDIT: Martin was faster … – Tobi Jul 04 '11 at 19:40
  • @Martin and Tobi: Thanks. That solved the problem. I had the feeling that I had to use some other command and looked in the manual for the answer but couldn't find it. Good thing you could help me out! – Speldosa Jul 04 '11 at 19:45
  • 2
    OT: It's times like these I'm wondering why I even bother using TikZ. Then again, when I see the final result, I remember why :) – Speldosa Jul 04 '11 at 19:46
  • 2
    @MartinScharrer It's possible to replace \def\myshift#1{\raisebox{1ex}} by raise=1ex \draw [->,thick,postaction={decorate,decoration={raise=-2.5ex,text along path,text align=center,text={|\sffamily|Some more bent text}}}] (One) to [bend right=45] (Two); I think that is valable since pgf 2.1 – Alain Matthes Dec 18 '11 at 17:15
  • 1
    Is there any way to put a fill on the "text along path" text? e.g. when using this over an image, it would make the text stand out better. I could not get the usual fill=white function to work. – Jonathan Komar Oct 24 '13 at 15:32
  • In the aforementioned example, text parameter text={|\sffamily\myshift|Some more bent text} works fine with plaintext. How can I use text with super-script here? I tried using the following text={|\sffamily\myshift|$value^a} but it does not work. – ex1led May 31 '21 at 11:58
  • @ex1led: try text={|\sffamily\myshift|value{${}^a$}}, but it might just work for single characters. – Martin Scharrer Jun 09 '21 at 07:00
38

You can use raise to place the text

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{decorations.text}

\begin{document}
\begin{tikzpicture}
\node (One) at (-3,0) [shape=circle,draw] {$One$}; 
\node (Two) at (3,0) [shape=circle,draw] {$Two$};
\draw [->,thick,postaction={decorate,decoration={raise=-2.5ex,text along path,text align=center,text={|\sffamily|Some more bent text}}}] (One) to [bend right=45]  (Two);
\draw [->,thick,postaction={decorate,decoration={raise=1ex,text along path,text align=center,text={|\sffamily|Some bent text}}}]      (One) to [bend left=45] (Two);
\end{tikzpicture}

\end{document}

enter image description here

Alain Matthes
  • 95,075
  • Using raise is not generally a good idea, as it'll increase inter-character space in the text along the path. Depending on one's specific situation, it may be better to \draw one path, and then \path another that is pushed slightly outward and along which the text is placed. – chsk Feb 12 '24 at 07:34
  • @chsk I'm not sure that writing bend text so that it follows a line is a good idea ! – Alain Matthes Feb 12 '24 at 09:55
  • perhaps I'm misunderstanding you, but isn't that what it's about? To give an example of what I meant: if you have e.g. \draw [postaction={decorate,decoration={raise=0.35cm,text along path,reverse path,text align=center,text={Text goes here}}}] (3,0) arc[radius=3cm, start angle=0, end angle=180];, then this will look bad, and you're better off \draw'ing the arc without the decoration, and then putting the text along another arc that's \path'ed rather than \draw'n and which has its radius (and starting coordinate) adjusted by 0.35cm. – chsk Feb 12 '24 at 11:52
25

The tikz library decorations.text allows you to place text along a path. The default placement of the text is not very nice if you are trying to have the text on a line (this seems to be because the default assumption is that the text is the line). You can use the \pgftransform... commands to shift the text around. These are described in Section 79 of the pgf manual. It's a bit cumbersome, since you can't use the node labels any more (they retain their coordinates). Here's your example with the text shifted as I suggested in my comment to Martin:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{decorations.text}
\begin{document}

\begin{tikzpicture}
\node (One) at (-3,0) [shape=circle,draw] {$One$}; 
\node (Two) at (3,0) [shape=circle,draw] {$Two$};
\draw [->, thick] (One) to [bend right=45]  (Two);
\pgftransformyshift{-.65cm}
\draw [decoration={text along path,
       text={Some more bent text},text align={center}},decorate]  (-3,0) to [bend right=45]  (3,0);
\draw [->, thick] (One) to  [bend left=45] (Two);
\pgftransformreset
\pgftransformyshift{.5cm}
\draw[decoration={text along path,
      text={Some bent text},text align={center}},decorate] (-3,0) to [bend left=45]  (3,0);
\node (mental) at (0,1.75) {};
\node (non-mental) at (0,-1.75) {};
\end{tikzpicture}


\end{document}

output of code

Alan Munn
  • 218,180