Ручные/автоматические переносы строк и выравнивание текста в узлах TikZ

Ручные/автоматические переносы строк и выравнивание текста в узлах TikZ

Как вставить разрыв строки в узел TikZ? Просто вставить \\разрыв там, где я хочу, не получится (см. MWE).

Есть ли способ сделать так, чтобы строки автоматически разрывались при достижении определенной ширины?

Могу ли я контролировать выравнивание текста (по левому краю, по правому краю, по центру, по ширине)?

\documentclass{article}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\node {First line\\second line};
\end{tikzpicture}
\end{document}

решение1

Проблема, по мнениюРуководство пользователя TikZ-PGFв том, что

Обычно при наборе узла весь текст, который вы указываете в фигурных скобках, помещается в одну длинную строку ( \hboxточнее, в ), и узел становится настолько широким, насколько это необходимо (§17.4.3).

Теперь в руководстве TikZ-PGF объясняются три способа, с помощью которых можно при желании добиться разрыва строки внутри узла TikZ.

  1. Используйте многострочную среду внутри узла.

Можно использовать среду внутри узла, которая вызывает разрыв строки или создает среду разрыва строки, чтобы добиться разрыва строки внутри узла. Пример в руководстве использует среду tabular:

\documentclass{article}

\usepackage{tikz}

\begin{document}

\begin{tikzpicture}
\node [draw] (example-tabular) {
\begin{tabular}{cc}
eaxmple1 & example2 \\
example 3 & example4 \\
\end{tabular}
};
\end{tikzpicture}

\end{document}

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

  1. Используйте \\и align.

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

\begin{tikzpicture}
\node (example-align) [draw, align=left]{example \\ example example};
\end{tikzpicture}

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

Преимущество этого варианта в том, что размер узла автоматически устанавливается на ширину самой длинной линии внутри узла, как можно увидеть на прилагаемом изображении, где ширина узла установлена ​​на ширину второй линии. Однако недостатком этого решения является то, что вам придется вручную контролировать разрыв строки самостоятельно (подробнее об этом ниже).

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

\begin{tikzpicture}
\node (example-align) [draw, align=left]{example \\[5em] example example};
\end{tikzpicture}

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

Однако следует отметить, что \\не может быть вложена в группу. Так, например, следующее будетнетработа.

\begin{tikzpicture}
\node (example-align) [draw, align=left]{\textbf{example \\ example example}};
\end{tikzpicture}

Вместо этого вам необходимо сделать следующее:

\begin{tikzpicture}
\node (example-align) [draw, align=left]{\textbf{example}\\\textbf{example example}};
\end{tikzpicture}
  1. Используйте text widthи \\(а может быть alignи ).

Наконец, третий вариант, отмеченный в руководстве TikZ-PGF, заключается в использовании аргумента text width, который, как я считаю, внутренне создает minipageокружение. Это решение вручную устанавливает ширину узла, и затем его можно использовать в сочетании с ручным разрывом строки:

\begin{tikzpicture}
\node (example-textwidth-1) [draw, text width=3cm]{example \\ example};
\end{tikzpicture}

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

Кроме того, его можно использовать с более длинным блоком текста, ширина которого по умолчанию больше ширины, указанной через text width. В таких случаях текст будет автоматически переноситься внутрь блока указанной ширины:

\begin{tikzpicture}
\node (example-textwidth-2) [draw, text width=3cm]{This is a demonstration text for showing how line breaking works.};
\end{tikzpicture}

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

Аргумент text widthтакже может использоваться в сочетании с alignаргументом для получения различных эффектов. Варианты для align, left, flush left, right, flush right, center, flush center, justifyи none. Подробности различных эффектов этих alignвариантов в сочетании с text widthаргументом см. в §17.4.3.

Вкратце, однако, flushварианты не пытаются сбалансировать левую и правую границы с помощью переносов. По моему мнению, результат часто выглядит не очень хорошо (см. рисунок), но его можно использовать, если по какой-то причине вы хотите избежать переносов.

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

(Верхний узел на рисунке выше использует align=left, а нижний узел использует align=flush left.)

Четвертый вариант

Четвертый, и я думаю, предпочтительный вариант, не обсуждаемый в руководстве TikZ-PGF, — это использованиеvarwidthpackage. Этот пакет по сути создает minipageокружение, но автоматически устанавливает горизонтальный размер окружения на самую широкую часть внутри него. Выше вы заметите, что опция text widthчасто делала узел больше, чем необходимо. Например, на изображении, воспроизведенном сразу ниже, вы можете видеть, что на правом поле есть дополнительное пространство:

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

Однако, если мы используем пакет varwidth, это дополнительное пространство устраняется,хотя оба настроены на 3cm:

\documentclass{article}

\usepackage{tikz}
\usepackage{varwidth}

\begin{document}

\begin{tikzpicture}
\node (example-textwidth-3) [draw, text width=3cm, align=left]{This is a demonstration text for showing how line breaking works.};
\end{tikzpicture}

\begin{tikzpicture}
\node (example-varwidth) [draw, align=left] {\begin{varwidth}{3cm}This is a demonstration text for showing how line breaking works.\end{varwidth}};
\end{tikzpicture}

\end{document}

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

Обсуждение

В целом, я думаю, что четвертый вариант наиболее предпочтителен, так как он делает узел максимально компактным (если, конечно, вы ненетхотите, чтобы узел был компактным).

Тем не менее, я считаю, что у четвертого варианта есть как минимум два недостатка, которые вам, возможно, стоит учесть, прежде чем решать, как вы хотите реализовать многострочный текст внутри узла TikZ, хотя я думаю, что первый недостаток этого варианта можно обойти.

Первый недостаток заключается в следующем: как отметил @percusse в комментариях, пакет varwidthфактически делает то же самое, что и alignузел, что, по-видимому, приводит varwidthк эффективному стиранию любых видимых различий между возможными вариантами для align. Таким образом, если вы хотите иметь выровненное по правому краю поле в своем узле и указываете его через align=right, не будет никакой видимой разницы между ним и, скажем, align=left. Однако это можно преодолеть, используяragged2epackage. Если вы хотите, чтобы ваш узел имел выровненное по правому краю поле, но при этом вы хотите, чтобы он был максимально компактным (и не хотите тратить время на ручную настройку text widthс помощью метода «угадай и проверь»):

\documentclass{article}

\usepackage{tikz}
\usepackage{varwidth}
\usepackage{ragged2e}

\begin{document}

\begin{tikzpicture}
\node (example-varwidth-left) [draw, align=left]{\begin{varwidth}{3cm}This is a demonstration text for showing how line breaking works.\end{varwidth}};
\end{tikzpicture}

\begin{tikzpicture}
\node (example-varwidth-right) [draw, align=right]{\begin{varwidth}{3cm}This is a demonstration text for showing how line breaking works.\end{varwidth}};
\end{tikzpicture}

\begin{tikzpicture}
\node (example-varwidth-ragged) [draw, align=flush right] {\begin{varwidth}{3cm}\RaggedLeft This is a demonstration text for showing how line breaking works.\end{varwidth}};
\end{tikzpicture}

\end{document} 

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

На изображении вы можете видеть, что между первыми двумя узлами нет никакой разницы, но использование команд, предоставляемых , ragged2eдает видимый эффект в третьем узле.

Второй недостаток четвертого варианта возникает, если вы действительно хотите контролировать перенос строк вручную. Среда varwidthвсе еще пытается сбалансировать строки с помощью переносов, что может привести, на мой взгляд, к некрасивым результатам:

\begin{tikzpicture}
\node (example-varwidth-linebreak) [draw, align=left]{\begin{varwidth}{3cm}This is a demonstration \\ text for showing how line breaking works.\end{varwidth}};
\end{tikzpicture}

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

Если вы хотите вручную контролировать перенос строк, я бы предложил второй вариант, указав аргумент alignи вставив \\' по своему усмотрению.

Обновление (согласно комментарию @percusse):

В случае, если вы хотите вручную контролировать переносы строк, второй вариант предпочтительнее четвертого, поскольку второй вариант устанавливает ширину узла равной длине самой длинной строки внутри узла. Никакого переноса текста и переносов не применяется. В результате, на мой взгляд, не будет никакого «уродливого» вывода от второго варианта именно потому, что никакой перенос текста и переносов не применяется.

Более того, вот почему я включил четвертый вариант в дополнение к трем, указанным в руководстве TikZ-PGF. Если вы хотите принудительно применить перенос текста внутри узла с определенной ширинойа также иметь максимально компактный размер узла, то вам нужно будет использовать varwidthсреду. Сравните следующие два узла, один с alignи один с varwidthустановленным значением 3cm:

\begin{tikzpicture}
\node (example) [draw, align=left]{This is a demonstration text for showing how line breaking works.};
\end{tikzpicture}

\begin{tikzpicture}
\node (example) [draw]{\begin{varwidth}{3cm}This is a demonstration text for showing how line breaking works.\end{varwidth}};
\end{tikzpicture}

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


Приложение

Строго говоря, это дополнение выходит за рамки вопроса; однако, учитывая предполагаемую природу этого вопроса, как указано в комментариях к вопросу, я подумал, что добавлю, что вы можете поместить любую из списочных сред ( itemize, enumerate, и description) внутрь узла, встроив ее либо в среду , minipageлибо varwidthв среду . Опять же, я думаю, что varwidthсреда предпочтительнее по причинам, перечисленным (без каламбура!) выше.

\documentclass{article}

\usepackage{tikz}
\usepackage{varwidth}
\usepackage{enumitem}

\begin{document}

\begin{tikzpicture}
\node [draw] (example-list) {
\begin{varwidth}{3cm}
\begin{enumerate}[leftmargin=*]
\item{First item}
\item{Second item}
\end{enumerate}
\end{varwidth}
};
\end{tikzpicture}

\end{document}

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

решение2

Если вы просто хотите разбить линию по точкам отсчета, достаточно разбить сам узел на несколько линий.

Например, из раздела 3.12 руководства TikZ, проект кода ниже

\begin{tikzpicture}
  \draw (0,0) -- (3,0) 
  node [above,align=center,midway]
  {
    First line \\
    Second Line
  };
\end{tikzpicture}

разрывает линию без необходимости использования дополнительных пакетов/инструментов.

ПРИМЕЧАНИЕ: этот метод не сработал у меня, когда узел один; только когда он является частью линии. Хотя никаких дополнительных пакетов не требуется.

Вывод скрипта:

Вывод скрипта TikZ без дополнительных пакетов

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