I would use the let
syntax for this (which requires the calc
library to be loaded). This has the advantage of not influencing the bounding box of your picture.
You can calculate the desired coordinate for the lower left corner of the B
node like this:
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}
\begin{document}
\begin{tikzpicture}
\draw (0,0) -- (2, 0) node (A) [draw, inner sep=5pt, pos=0.5, anchor=south] {A};
\draw let \p1 = (0,0),
\p2 = (2,-3),
\p3 = (A.south west) in
(\p1) -- (\p2) node at (\x3, {(\y2-\y1)*\x3/(\x2-\x1)}) [name=B,draw, inner sep=5pt, anchor=south west] {B};
\end{tikzpicture}
\end{document}
And here's a different approach that allows the nodes to be of different widths, as per Andrew Stacey's suggestion.
The idea is to use a diamond
node which contains the rectangular node as payload. By setting the shape aspect
according to the slope of the line and anchoring its lower corner on the desired position along the line, the rectangle node will change its position according to the width of the content.
I used a matrix of nodes
for the outer node, which allows the inner node to be correctly handled by TikZ (you could also use a normal node and define the inner node using \tikz \node ...;
, but this kind of nesting leads to problems). Using a matrix of nodes
means that you have to terminate your node using \\
.
I wrapped the calculations and style settings into a corner on line
style, which passes its arguments to the inner node.
Here are two examples:
\draw (0,0) -- (4, 0) node (A) [draw, inner sep=5pt, pos=0.5, anchor=south] {A};
\draw let \p1 = (0,0),
\p2 = (3,-5),
\p3 = (A.south) in
(\p1) -- (\p2)
node [corner on line={draw, inner sep=5pt}] {B\\ }
node [corner on line={draw, inner sep=5pt}] {Engorgio!\\ }
;
will yield
And here are the same examples with the outer node drawn in colour
\draw (0,0) -- (4, 0) node (A) [draw, inner sep=5pt, pos=0.5, anchor=south] {A};
\draw let \p1 = (0,0),
\p2 = (3,-5),
\p3 = (A.south) in
(\p1) -- (\p2)
node [corner on line={draw=black, inner sep=5pt}, draw=blue] {B\\ }
node [corner on line={draw=black, inner sep=5pt}, draw=red] {Engorgio!\\ }
;
Here's the complete code:
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc, shapes.geometric, matrix}
\tikzset{
calculate slope/.code={
\pgfmathsetmacro\aspect{abs((\x2-\x1)/(\y2-\y1))}
\tikzset{shape aspect=\aspect}
},
corner on line/.style={
at={(\x3, {(\y2-\y1)*\x3/(\x2-\x1)})},
matrix of nodes,
diamond,
anchor=south,
inner sep=0pt,
outer sep=-0.5\pgflinewidth,
calculate slope,
nodes={
rectangle,
#1
}
}
}
\begin{document}
\begin{tikzpicture}
\draw (0,0) -- (4, 0) node (A) [draw, inner sep=5pt, pos=0.5, anchor=south] {A};
\draw let \p1 = (0,0),
\p2 = (3,-5),
\p3 = (A.south) in
(\p1) -- (\p2)
node [corner on line={draw=black, inner sep=5pt}, draw=blue] {B\\ }
node [corner on line={draw=black, inner sep=5pt}, draw=red] {Engorgio!\\ }
;
\end{tikzpicture}
\end{document}
Best Answer
The already mentioned
tabbing
package has the disadvantage that it cannot be used across paragraphs, for instance, in itemize environments, as asked in this related question.However, the
tabto
package provides exactly what you are looking for via the command\tabto*
: