Как можно явно задать привязку метки TikZ?

Как можно явно задать привязку метки TikZ?

Я хочу добавить labelк узлу, но "внутри" узла. Что-то вроде этого:

желаемый результат

В руководстве, похоже, указано, что это возможно, хотя конкретный ключ не назван.

... Точка привязки для узла метки ... определяется таким образом, что узел метки будет «отвернут» от границы основного узла. Выбранная точка привязки зависит от положения выбранной точки границы и ее положения относительно центра основного узла, а также от того, установлена ​​ли опция трансформации формы.В целом выбор должен быть таким, какой вы ожидаете, но в сложных ситуациях вам, возможно, придется устанавливать якорь самостоятельно.(выделено мной)

Но когда я пробую такой пример:

\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\tikz \node [circle,draw,label={[red,anchor=north]above:X}] {my circle};
\end{document}

Я не вижу никаких изменений в положении узла метки. Он по-прежнему «снаружи».

фактический выход

Есть идеи?

решение1

Проблема здесь в том, что TikZ применяет некоторую автоматизацию (а именно макрос \tikz@auto@anchor), которая перезапишет ваш набор anchor.

Мы можем либо перехватить .codeключ, который применяется последним в узле, который используется внутри для метки (да, даже после наших собственных настроек red, anchor=north) и который вызывает \tikz@auto@anchor:

\tikzset{label anchor/.style={tikz@label@post/.append style={anchor=#1}}}

или позволим макросу, который выполняет вычисления, немного расслабиться (дополнительный ключ не нужен):

\tikzset{anchor/.append code=\let\tikz@auto@anchor\relax}

Если новый и улучшенный anchorключ теперь будет использоваться более глобально (например, \tikz[anchor=<dir>]), это также повлияет на узлы (и в настоящее время есть способ вернуть его).

Я также предоставляю ключ inside(вы даже можете использовать его дважды, чтобы обратить эффект).

Код

\documentclass[tikz]{standalone}
\usepackage{etoolbox}
\makeatletter
\tikzset{anchor/.append code=\let\tikz@auto@anchor\relax}
\tikzset{inside/.code=\preto\tikz@auto@anchor{\pgf@x-\pgf@x\pgf@y-\pgf@y}}
\makeatother
\begin{document}
\tikz\node [anchor=west, circle,draw,label={[red, anchor=north]above:X}] {my circle};
\tikz\node [anchor=west, circle,draw,label={[red, inside]below:X}] {my circle};
\end{document}

Выход

введите описание изображения здесь

введите описание изображения здесь

решение2

Вот еще один подход, эксплуатирующий эту append after commandопцию. Суть в том, что, ссылаясь на якорь, \tikzlastnode.centerможно добавлять, относительно этой позиции, ярлыки.

Новый стиль, способный выполнить эту задачу my label:

\tikzset{my label/.style args={#1:#2}{
  append after command={
    (\tikzlastnode.center) node [#1] {#2}
    }
  }
}

А мве:

\documentclass[tikz,png,border=10pt]{standalone}
\usepackage{tikz}
\tikzset{my label/.style args={#1:#2}{
    append after command={
       (\tikzlastnode.center) node [#1] {#2}
    }
  }
}
\begin{document}
\tikz \node [circle,draw,my label={red,above=0.15cm:X}] {my circle};
\tikz \node [circle,draw,my label={red,below=0.15cm:X}] {my circle};
\end{document}

что дает в качестве результатов:

введите описание изображения здесь

введите описание изображения здесь

Стиль принимает в качестве первого аргумента любой параметр TikZ, поэтому легко настраивать цвета и положение: действительно, лучше немного отрегулировать смещение, чтобы не перекрывать текст.

Если же вы знаете, что метку всегда следует размещать под «северной границей», то лучшим решением будет изменить стиль my labelна:

\tikzset{my label/.style args={#1:#2}{
    append after command={
       (\tikzlastnode.north) node [#1] {#2}
    }
  }
}

Таким образом, просто установив:

\tikz\node [circle,draw,my label={red,below:X}] {my circle};

позволяет достичь цели.

А мве:

\documentclass[tikz,png,border=10pt]{standalone}
\usepackage{tikz}
\tikzset{my label/.style args={#1:#2}{
    append after command={
       (\tikzlastnode.north) node [#1] {#2}
    }
  }
}
\begin{document}
\begin{tikzpicture}
\node [circle,draw,my label={red,below:X}] {my circle};
\node [circle,draw,my label={red,below=0.15cm:X},xshift=2cm] {my circle};
\end{tikzpicture}
\end{document}

Результат:

введите описание изображения здесь

Пересмотр

Предыдущий метод страдает, как сказано в комментариях, если нужно ввести более одной метки. Но это вполне осуществимо, если вместо введения узлов мы вводим координаты с метками.

Код:

\documentclass[tikz,png,border=10pt]{standalone}
\usepackage{tikz}
\tikzset{my label/.style args={[#1]#2:#3}{
    append after command={
       (\tikzlastnode.center) coordinate[label={[label distance=0.1cm,#1]#2:#3}]
    }
  },
}
\begin{document}
\begin{tikzpicture}
\node [circle,
  draw,
  my label={[red]above:X},
  my label={[green!70!blue]below:Y},
  my label={[blue,yshift=0.3cm]above:Z}] {my circle};
\node [circle,
  draw,
  my label={[blue,yshift=-0.15cm]below:X},
  my label={[green!70!blue]70:Z},
  my label={[orange!80!red]130:Y},
  xshift=2cm] {my circle};
\end{tikzpicture}
\end{document}

Результат:

введите описание изображения здесь

Примечание: использование label distanceв определении параметра позволяет не допустить перекрытия текста метки, когда просто говорится:

\tikz\node [circle,draw,my label={[red]below:X}] {my circle};

решение3

Вы также можете сместить метку:

\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\tikz \node [circle,draw,label={[red,yshift=-0.5cm]above:X}] {my circle};

\tikz \node [circle,draw,label={[red,label distance=-0.5cm]above:X}] {my circle};
\end{document}

Связанный контент