I'm very keen on seeing other people's approaches to this, but in the meantime I'll post what I came up with:
The following code defines a new tikzstyle
that creates a vertical path at a specified position in the plot, intersects that line with the plot, and adds something like a glorified pin
(actually a line with a label
at the end, which gives finer control over the text placement than just a pin
) at the intersection.
It takes three arguments:
- The position of the vertical line, specified as a fraction of the plot width (0 is the left edge, 1 the right)
- The position of the label relative to the intersection of the line and plot. It can be given as polar coordinates (
{45:1cm}
) or a relative coordinate ({0.4cm,2cm}
) and has to be enclosed in curly braces.
- The label text, or, more accurately the
label
code: Either just the text, or something like {[red]left:<text>}
to position the label to the left of the end of the label line and colour it red.
It's not exactly what I asked for, in that it does not position the label at a given distance along the graph, but rather at a fixed horizontal distance along the plot canvas. I find this to be more of a feature than a shortcoming, though, because it allows for nice alignments of the labels. Using other paths for defining the intersections, like horizontal lines or circles instead of the vertical line, is easily possible.
\documentclass{article}
\usepackage{pgfplots}
\usetikzlibrary{intersections}
\pgfkeys{/pgfplots/linelabel/.style args={#1:#2:#3}{name path global=labelpath,execute at end plot={
\path [name path global = labelpositionline]
(rel axis cs:#1,0) --
(rel axis cs:#1,1);
\draw [help lines,text=black,inner sep=0pt,name intersections={of=labelpath and labelpositionline}] (intersection-1) -- +(#2) node [label={#3}] {};},
}}
\begin{document}
\begin{tikzpicture}
\begin{axis}
\addplot +[linelabel=0.8:{-45:0.75cm}:{[blue]right:$x^2$}] {x^2};
\addplot +[linelabel=0.8:{-.6cm,.6cm}:$1.5x^2$] {1.5*x^2};
\end{axis}
\end{tikzpicture}
\end{document}

A way of placing labels at a specified position along the plot path, based on the answer to How determine slope of straight line (with auto scale of axis) in PGF plots
Alternatively, a decoration can be used to place label nodes. The decorations.markings
library allows to place a node somewhere along a path. To use the decoration in \addplot
, it has to be applied it through an every path/.style
, which leads to a problem with the decoration being applied to itself. Thankfully, this has been solved already: Applying a postaction to every path in TikZ.
Also, PGFplots seems to have a problem with using TikZ nodes in the decorations. This can be avoided by using \pgfnode
instead, which does exactly the same as \node
, but looks a bit unusual.
Here's an example where a plotlabel
style is defined (based on Altermundus' idea in How to label a path drawn using tikz with \draw plot?, and adapted to work around the described problems). You specify the label with plotlabel={<rel pos along path>}{<label text>}
. To change the color of the label, \color{<color name>}<label text>
can be used. The plotlabel
option can be used multiple times to add different labels to the same plot.
\documentclass{article}
\usepackage{pgfplots}
\usetikzlibrary{decorations.markings}
\makeatletter
\tikzset{
nomorepostaction/.code={\let\tikz@postactions\pgfutil@empty},
plotlabel/.style 2 args={
every path/.append style={
postaction={
nomorepostaction,
decorate,
decoration={
markings,
mark=at position #1 with {
\pgftransformresetnontranslations
\pgfsetlinewidth{0.4pt}
\pgfsetstrokecolor{black}
\pgfpathmoveto{\pgfpointorigin}
\pgfpathlineto{\pgfpoint{-0.3cm}{0.6cm}}
\pgfusepath{stroke}
\pgftransformshift{\pgfpoint{-0.3cm}{0.6cm}}
\pgfnode{rectangle}{east}{#2}{}{}
}
}
}
}
}
}
\makeatother
\begin{document}
\begin{tikzpicture}
\begin{axis}[
axis y line=center,
axis x line=middle,
axis on top=true,
xmin=-7,
xmax=7,
ymin=-4,
ymax=4,
clip=false
]
\addplot[
mark=none,
domain=-4:6,
samples=80,
red,
thick,
plotlabel={0.1}{\color{purple}$f(x)=-2$},
plotlabel={0.6}{\color{blue}$f(x)=x$},
plotlabel={0.9}{\color{green!70!black}$f(x)=3$}
] {(x<-2)*-2 + (!(x<-2) && (x<3))*x + (!(x<3)) * 3};%
\end{axis}
\end{tikzpicture}
\end{document}
