
Как вставить разрыв строки в узел 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.
- Используйте многострочную среду внутри узла.
Можно использовать среду внутри узла, которая вызывает разрыв строки или создает среду разрыва строки, чтобы добиться разрыва строки внутри узла. Пример в руководстве использует среду 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}
- Используйте
\\
и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}
- Используйте
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, — это использованиеvarwidth
package. Этот пакет по сути создает 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
. Однако это можно преодолеть, используяragged2e
package. Если вы хотите, чтобы ваш узел имел выровненное по правому краю поле, но при этом вы хотите, чтобы он был максимально компактным (и не хотите тратить время на ручную настройку 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}
разрывает линию без необходимости использования дополнительных пакетов/инструментов.
ПРИМЕЧАНИЕ: этот метод не сработал у меня, когда узел один; только когда он является частью линии. Хотя никаких дополнительных пакетов не требуется.
Вывод скрипта: