2

I want to draw a node A that has the same width as a node B. But node B should not be drawn. How can I get B's width?

dexteritas
  • 9,161

2 Answers2

2

This is in part based on Creating a node fitting the horizontal width of two other nodes

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}
\begin{document}
\begin{tikzpicture}
\node[draw = none] at (0,-1) (B) {\phantom{This node should be hidden}};
\path let \p1=($(B.west)-(B.east)$),
    \n1 = {veclen(\p1)-\pgflinewidth}
    in node[minimum width=\n1,draw] at (0,-1) (A) {foobar};
\end{tikzpicture}
\end{document}

enter image description here

  • 1
    You can also create a phantom node by just setting opacity=0 (which will affect border, fill, and text). – Emma Oct 27 '16 at 17:40
  • Using opacity=0 still leaves the text selectable, though. – 804b18f832fb419fb142 Oct 27 '16 at 17:47
  • As I understand it, the node will be drawn in the end. Hence, the text's being selectable doesn't seem to be an issue in this case. – cfr Oct 27 '16 at 23:35
  • In my use case I generate the LaTeX code in Matlab. I need the width of a node that will be added to the .tex file later and at a yet unknown position (due to relative positioning). But I think this less specific question & answer is more useful. I edited the question to reflect this. – 804b18f832fb419fb142 Oct 28 '16 at 00:00
  • 1
    If you don't have any funky text (math stuff or font switches) you can go about it with \node[minimum width={width("This node should be hidden")},draw] at (0,-1) (A) {foobar}; – percusse Oct 28 '16 at 00:06
  • In some cases that could be a solution, but I need A's and B's (if it were displayed) frame to have the same width. – 804b18f832fb419fb142 Oct 28 '16 at 00:13
  • Your edit means my answer no longer makes sense. Thanks a bunch. – cfr Oct 28 '16 at 00:39
  • I don't know what A's and B's refer to. – percusse Oct 28 '16 at 07:52
1

This answer addresses the original question before it was edited in a way which renders this answer inapplicable.

Of course, you could never draw the saved node, but that would be an unnecessarily circuitous route.

It is possible to save a constructed node and draw it later. This means that you can save the node, measure it, use the result to do something else and then draw the original node.

The basic method is demonstrated on page 1030 of the TikZ manual in the PGF section. I define some additional convenience commands which let us write

\begin{tikzpicture}
  \mylaternode [fill=magenta, blend mode=normal, draw=magenta, fill opacity=.5, draw opacity=.75] (hi) {Hello world};

\mylaternode should hopefully work just like \node except that we should not position it i.e. we don't want an at or anything. This commands makes available \mylaternodewidth which stores the width of the node less the current line width. This is correct if the nodes are drawn. If not, you would need to adjust the definition or manually add the width back in.

We can now use this to construct another node of matching width.

  \node [top color=blue!50!cyan, bottom color=blue!50!cyan, middle color=white, minimum height=20mm, minimum width=\mylaternodewidth, draw=blue!50!cyan] at (10mm,10mm) {};

Finally, we use \placemynode(<x>,<y>) to actually draw the saved node.

  \placemynode(10mm,10mm)
\end{tikzpicture}

Finishing the picture, we get the following result.

hello world! (later)

\documentclass[border=10pt,multi,tikz]{standalone}
\begin{document}
% adapted from manual 1030
\newbox\mybox
\newcommand*\mysaver{%
  \global\setbox\mybox=\box\pgfpositionnodelaterbox
  \global\let\myname=\pgfpositionnodelatername
  \global\let\myminx=\pgfpositionnodelaterminx
  \global\let\myminy=\pgfpositionnodelaterminy
  \global\let\mymaxx=\pgfpositionnodelatermaxx
  \global\let\mymaxy=\pgfpositionnodelatermaxy
  \pgfmathsetlengthmacro\mylaternodexlength{abs(\mymaxx-\myminx)-\pgflinewidth}%
  \global\let\mylaternodewidth=\mylaternodexlength
}
\newcommand*\myrestorer{%
  \let\pgfpositionnodelatername=\myname
  \let\pgfpositionnodelaterminx=\myminx
  \let\pgfpositionnodelaterminy=\myminy
  \let\pgfpositionnodelatermaxx=\mymaxx
  \let\pgfpositionnodelatermaxy=\mymaxy
  \setbox\pgfpositionnodelaterbox=\box\mybox
}
\def\mylaternode#1;{%
  {%
    \pgfpositionnodelater{\mysaver}
    \node #1;
  }%
}
\def\placemynode(#1,#2){%
  \myrestorer
  \pgfpositionnodenow{\pgfqpoint{#1}{#2}}%
}
\begin{tikzpicture}
  \mylaternode [fill=magenta, blend mode=normal, draw=magenta, fill opacity=.5, draw opacity=.75] (hi) {Hello world};
  \node [top color=blue!50!cyan, bottom color=blue!50!cyan, middle color=white, minimum height=20mm, minimum width=\mylaternodewidth, draw=blue!50!cyan] at (10mm,10mm) {};
  \placemynode(10mm,10mm)
\end{tikzpicture}
\end{document}
cfr
  • 198,882