
Я хочу нарисовать линию между 2 узлами, которая может пролететь через существующую форму и текстовое содержимое. В примере ниже линия, соединяющая a
и b
пересекающаяся с меткой init
узла. Я могу вручную сделать "пролет линии" после того, как замечу факт из результата tikz. Но есть ли какое-то средство, которое может оценить такие обстоятельства и выполнить автоматическую обработку на ходу? Что-то вроде\draw [flyline, ->] (a) to (b)
\documentclass[convert]{standalone}
\usepackage{tikz}
\usetikzlibrary{shapes, positioning}
\begin{document}
\begin{tikzpicture}[auto]
\node[rectangle, draw=black, label={right:this is a test}] (init) {hello};
\node[rectangle, draw=black, above right=of init] (a) {a};
\node[rectangle, draw=black, below right=of init] (b) {b};
\draw [->] (a) to (b);
% I can change to use this after I find the intersect fact from the result
%\draw (a) to (a|-init.north);
%\draw [->] (b|-init.south) to (b);
\end{tikzpicture}
\end{document}

Обновление: Ответ на комментарий @Rmano: Спасибо за ответ. Да, использование слоя может частично решить мою проблему. Я использовал пакет `tikz-layers`, который предоставляет 5 предопределенных слоев. Фрагменты кода следующие:
\documentclass[convert]{standalone}
\usepackage{tikz}
\usetikzlibrary{shapes, positioning, fit}
\usepackage{tikz-layers}
\begin{document}
\begin{tikzpicture}[auto]
\node[rectangle, draw=black, label={[fill=white, inner sep=2pt, name=lbl]right:this is a test}] (init) {hello};
\node[rectangle, draw=black, above right=of init] (a) {a};
\node[rectangle, draw=black, below right=of init] (b) {b};
\begin{scope}[on behind layer]
\draw [->] (a) to (b);
\end{scope}
\begin{scope}[on background layer]
\node [fit=(init)(a)(b)(lbl), fill=cyan] () {};
\end{scope}
\end{tikzpicture}
\end{document}
Что дает следующий результат

Одна вещь, которая мне кажется не совсем идеальной, заключается в том, что это делает так, что метка покрывает фоновую заливку. Изначально label
это был только текст, теперь он приобретает форму, которая непрозрачна для фоновой заливки. Мы можем изменить заливку метки так же, как и фоновую заливку cyan
, но это создаст другую зависимость.
Возможно ли, что label
может иметь виртуальную границу, которая только маскирует подчеркивание, draw
но не само подчеркивание fill
?
Обновление: согласно предложению @Rmano использовать `contour`, обновите MWE до следующего
\documentclass[convert]{standalone}
\usepackage{tikz}
\usetikzlibrary{shapes, positioning, fit}
\usepackage{tikz-layers}
\usepackage{bidicontour}
\usepackage{bidi}
\bidicontourlength{2pt}
\begin{document}
\begin{tikzpicture}[auto]
\node[rectangle, draw=black, label={[inner sep=2pt, name=lbl]right:{\bidicontour{cyan}{this is a test}}}] (init) {hello};
\node[rectangle, draw=black, above right=of init] (a) {a};
\node[rectangle, draw=black, below right=of init] (b) {b};
\begin{scope}[on behind layer]
\draw [->] (a) to (b);
\end{scope}
\begin{scope}[on background layer]
\node [fit=(init)(a)(b)(lbl), fill=cyan] () {};
\end{scope}
%\draw (a) to (a|-init.north);
%\draw [->] (b|-init.south) to (b);
\end{tikzpicture}
\end{document}
Что дает почти идеальный результат

Спасибо за помощь!
решение1
Возможно ли, что
label
может иметь виртуальную границу, которая только маскирует подчеркивание,draw
но не само подчеркиваниеfill
?
Думаю, нет.
Также, по моему мнению, нет большой разницы между написанием label={[fill=cyan]text}
и label={[...]\bidicontour{cyan}{text}}
. Всегда нужно явно писать цвет фона вlabel={...}
.
Следующий пример показывает попытку написать цвет фона только один раз. Определениеpgfonlayerreversed
окружения скопировано из моегопредыдущий ответ.
\documentclass[tikz]{standalone}
\usetikzlibrary{backgrounds, shapes, positioning, fit}
\usepackage{xpatch}
\makeatletter
% copied from my previous answer https://tex.stackexchange.com/a/562606
\let\pgfonlayerreversed\pgfonlayer
\let\endpgfonlayerreversed\endpgfonlayer
\xpatchcmd\pgfonlayerreversed
{\expandafter\box\csname pgf@layerbox@#1\endcsname\begingroup}
{\begingroup}
{}{\fail}
\xpatchcmd\endpgfonlayerreversed
{\endgroup}
{\endgroup\expandafter\box\csname pgf@layerbox@\pgfonlayer@name\endcsname}
{}{\fail}
% similar to \tikz@background@framed, but using "pgfonlayerreversed" envi
\def\tikz@background@framed@reversed{%
\tikz@background@save%
\pgfonlayerreversed{background}
\path[style=background rectangle] (\tikz@bg@minx,\tikz@bg@miny) rectangle (\tikz@bg@maxx,\tikz@bg@maxy);
\endpgfonlayerreversed
}%
% similar to option "show background rectangle"
\tikzset{
show background rectangle reversed/.style={
execute at end picture=\tikz@background@framed@reversed
}
}
\makeatother
% user interface
\tikzset{
background color/.style={
show background rectangle reversed,
inner frame sep=2pt,
background rectangle/.append style={draw=none, #1},
every node/.append style={#1},
every label/.append style={#1}
}
}
\begin{document}
\begin{tikzpicture}[background color={fill=cyan}]
\node[draw, label={[inner sep=2pt, name=lbl]right:this is a test}] (init) {hello};
\node[draw, above right=of init] (a) {a};
\node[draw, below right=of init] (b) {b};
\begin{scope}[on background layer]
\draw [->] (a) to (b);
\end{scope}
\end{tikzpicture}
\end{document}