Как уже обсуждалось в предыдущем посте из серии "ЛаТеХ для продвинутых", одним из самых универсальных средств для контроля над расположением картинок, таблиц и подписей к ним в пределах плавaющего объекта является пакет floatrow.
В предыдущей части
мы рассмотрели всевозможные способы
взаимного расположения картинки и подписи (снизу, сверху, сбоку),
выравнивания их по горизонтали и т.п.
Этот же пост будет посвящён
расположению нескольких объектов (рисунков, таблиц) в ряд.
Обратите внимание, что
имеется в виду именно расположение нескольких объектов
типа figure и/или table, а не нескольких картинок/таблиц (обычно
помеченных как а, б, в, ...) в пределах
одного объекта, как это делают пакеты subcaption
или subfig
.
Все примеры из данного поста могут быть найдены
здесь
и
здесь
в виде tex-файлов готовых к компиляции. Документация к пакету
floatrow
доступна на
русском и
английском языках.
Краткий анонс
Сначала мы познакомимся с командами
\ffigbox{}{}
и \ttabbox{}{}
, которые создают
бокс для картинки/таблицы и соответствующей подписи.
Затем будут освещены средства, необходимые для контроля над горизонтальным выравниванием:
- Окружение floatrow для расположения иллюстраций и таблиц в ряд.
- Длины FBwidth (ширина картинки) и Xhsize (ширина остатка страницы).
- Параметр floatrowsep, определяющий расстояние между картинками в ряду.
И, наконец, будут разобраны способы выравнивания объектов по вертикали, как то
- Команды
\TopFloatBoxes
,\BottomFloatBoxes
,\CenterFloatBoxes
, выравнивающие весь float. - Параметры
heightadjust
иvalign
для выравнивания только картинки/таблицы. - Выравнивание подписей.
Команда \ffigbox
Основной рабочей лошадкой во всех примерах ниже является команда
\ffigbox
предоставляемая пакетом floatrow
.
Её синтаксис прост:
Она определяет бокс, в который помещается картинка и подпись к ней, например01:
\ffigbox
[ширина][высота][вертикальное положение]{подпись}{картинка}
создаст обычный плавающий объект, как произошло бы и без использования01:
\usepackage
{floatrow}02:
\usepackage
{graphicx}03:
...04:
\begin
{figure
}[!h]05:
\ffigbox
{\caption
{My Caption}\label
{fig:ffb}}%
06:
{\includegraphics
{roman_a}}07:
\end
{figure
}
\ffigbox
, с той единственной разницей, что благодаря
\ffigbox
автоматически включается горизонтальное
выравнивание по центру.
Для таблиц определена аналогичная команда \ttabbox
:
далее мы сосредоточимся на картинках, но всё без исключения применимо и
к таблицам.
Расположить несколько рисунков в ряд нам поможет окружение
floatrow
:
01:
\begin
{figure
}02:
\begin
{floatrow}03:
\ffigbox
{\caption
{My Caption left}\label
{...}}%
04:
{\includegraphics
{...}}05:
\ffigbox
{\caption
{My Caption right}\label
{...}}%
06:
{\includegraphics
{...}}07:
\end
{floatrow}08:
\end
{figure
}
По умолчанию, страница просто поделена на две равные по ширине части, в каждую из которых вставлен рисунок и отцентрирован по горизонтали. Просто и незатейливо,... но не всегда достаточно, чтобы добиться идеального результата. Итак, за дело: в путь к идеалу!
Горизонтальное выравнивание
Волшебная длина \FBwidth
Предыдущий рисунок выглядит очень неуравновешенно, так как ширина отводящаяся на подпись не соответствует ширине картинки. Гораздо более симпатичного результата можно добиться вот так:
01:
\usepackage
{floatrow,graphicx,calc}02:
% Создаёем новый разделитель
03:
\DeclareFloatSeparators
{mysep}{\hspace
{3cm}}04:
...05:
% Настраиваем значение разделителя для объектов
06:
\thisfloatsetup
{floatrowsep=mysep}07:
% А вот и сам плавающий объект
08:
\begin
{figure
}09:
\begin
{floatrow}10:
\ffigbox
[\
FBwidth
+1cm]{\caption
{...}}%
11:
{\includegraphics
{...}}12:
\ffigbox
[\
FBwidth
+1cm]{\caption
{...}}%
13:
{\includegraphics
{...}}14:
\end
{floatrow}15:
\end
{figure
}
По порядку
- В строках 10 и 12 использован необязательный аргумент в
\ffigbox
, который задаёт ширину плавающего объекта. В этом примере мы задаём ширину на 1см больше, чем ширина соответствующего изображения: т.е. подпись будет выдаваться на 0.5см с каждой стороны. Заметьте, что ширина самого изображения доступна через\FBwidth
, a для того, чтобы можно было к ней прибавить 1см, надо загрузить пакетcalc
в строке 1. -
Расстояние между двумя объектами (Figure 3 и Figure 4) задано в строке 6
с помощью параметра
floatrowsep
. Обратите внимание, что нельзя просто написатьfloatrowsep=3cm
, вместо этого надо определить новый разделитель (назовём егоmysep
) в строке 3, а затем использовать вfloatrowsep=mysep
. Пакет предопределяет следующие разделители:none
,quad
(=1em),qquad
(=2em),columnsep
(равен длине\columnsep
, которую ЛаТеХ использует для разделения двух колонок текста).
Волшебная длина \Xhsize
Помимо очень полезной длины \FBwidth
, пакет предопределяет
длину (точнее, ширину) \Xhsize
,
равную оставшейся ширине
страницы. Эта длина может быть использована точно так же, как и
\FBwidth
, в первом необязательном аргументе
\ffigbox
.
Например, в случае, когда одна из подписей очень длинная, под неё может быть желательно выделить побольше места:
01:
\begin
{figure
}02:
\begin
{floatrow}03:
\ffigbox
[\FBwidth
+1cm]{\caption
{My Caption left}}%
04:
{\includegraphics
{...}}05:
\ffigbox
[\
Xhsize
]{\caption
{My Caption right very .... very long}}%
06:
{\includegraphics
{...}}07:
\end
{floatrow}08:
\end
{figure
}
Несколько картинок в ряд
До сих пор мы рассматривали расположение только лишь двух
рисунков в ряд. Однако, ситуацию легко обобщить для произвольного
числа рисунков. Для этого небходимо задать необязательный аргумент
к окружению floatrow
равным числу рисунков, как
проиллюстрированно в третьей строке нижеследующего примера.
01:
\thisfloatsetup
{floatrowsep=qquad}02:
\begin
{figure
}03:
\begin
{floatrow}[3]
% три рисунка в ряд!
04:
\ffigbox
[\FBwidth
+0.5cm]{\caption
{...}}{\includegraphics
{...}}05:
\ffigbox
[\Xhsize
/3*2]{\caption
{...}}{\includegraphics
{...}}06:
\ffigbox
[\Xhsize
]{\caption
{...}}{\includegraphics
{...}}07:
\end
{floatrow}08:
\end
{figure
}
Из этого же примера очевидна гибкость использования \FBwidth
и \Xhsize
: к ним можно прибавлять длины, их можно
умножать на скаляры. Кроме того, обратите внимание, что
параметр \Xhsize
в строках 5 и 6 имеет разные значения:
он каждый раз означает ширину, оставшуюся на странице
на момент вызова \ffigbox
!
Вертикальное выравнивание
Весь объект
До сих пор во всех примерах использовались картинки приблизительно одинаковой высоты, т.е. особой нужды в форматировании их вертикального положения не возникало. Если же рисунки отличаются по высоте, то встаёт вопрос об их вертикальном положении относительно друг друга.
Эта проблема решается с помощью одной из команд
\BottomFloatBoxes
(выравнивание по низу),
\TopFloatBoxes
(выравнивание по верху),
\CenterFloatBoxes
(выравнивание по центру),
которая должна следовать сразу после \begin{figure}
.
приводит к такому результату:01:
\begin
{figure
}[!h]\TopFloatBoxes
% or \BottomFloatBoxes or \CenterFloatBoxes
02:
\begin
{floatrow}03:
\ffigbox
{...}{...}04:
\ffigbox
{...}{...}05:
\end
{floatrow}06:
\end
{figure
}
Только картинки
В большинстве случаев, однако, необходимо выровнять только картинки, а подписи к ним оставить на одном уровне. Без проблем:
01:
\begin
{figure
}[!h]02:
\floatsetup
{heightadjust=object,valign=c
}03:
\begin
{floatrow}04:
\ffigbox
{\caption
{...}}%
05:
{\includegraphics
{...}}06:
\ffigbox
{\caption
{...}}%
07:
{\includegraphics
{...}}08:
\end
{floatrow}09:
\end
{figure
}
Здесь использованы два параметра:
heightadjust
: какие части float в ряду должны быть
одинаковой высоты. Соответственно, его значения
object
: место, отводящееся под саму картинку, выполнить одинаковой высоты для всех картинок;caption
: то же, но для места, отводящегося под подпись;all
: первое и второе вместе;noobject
,nocaption
,none
: отрицание, соответственно, первого, второго и третьего
floatrow
инструктирован выделить под
обе картинке блоки одинаковой высоты.
valign
: "тип" вертикального выравнивания. Может быть
t
(по верху), b
(по низу), c
(по центру).
Подписи
Для рисунков, когда подписи размещены под иллюстрацией, нет необходимости их дополнительно "выравнивать": подписи и так выровнены "по верху". Однако у таблиц, когда подписи размещены сверху, так как использована директива
или, что то же самое,01:
\floatsetup
[table]{style=plaintop}
то подписи автоматически оказываются вырoвненными "по низу", вот так:01:
\floatsetup
[table]{capposition=top}
Чтобы вырoвнять их "по верху" используем
или же01:
\floatsetup
[table]{style=Plaintop}
01:
\floatsetup
[table]{capposition=TOP}
Полностью код примера выше: открыть
01:
% используем стиль, в котором подписи таблиц
02:
% сверху и выравнены "по верху"
03:
\floatsetup
[table]{style=Plaintop,floatrowsep=qquad}04:
%
05:
% Теперь сами таблицы в ряд
06:
\begin
{table}[!h]07:
\begin
{floatrow}08:
% первая таблица
09:
\ttabbox
[\FBwidth
]{\caption
{My Caption left}}%
10:
{\begin
{tabular
}{c|cc}11:
Column 1 & Column 2 & Column 3\
\
\hline
12:
a & b & c\
\
13:
a & b & c\
\
14:
a & b & c\
\
15:
a & b & c\
\
16:
a & b & c17:
\end
{tabular
}18:
}19:
% вторая таблица
20:
\ttabbox
[\FBwidth
]{\caption
{My Caption right, let us21:
make it somewhat longer}}%
22:
{\begin
{tabular
}{c|cc}23:
Column 1 & Column 2 & Column 3\
\
24:
\hline
25:
a & b & c\
\
26:
a & b & c\
\
27:
a & b & c28:
\end
{tabular
}29:
}30:
\end
{floatrow}31:
\end
{table}
Картинка рядом с таблицей
Все трюки, приведённые выше, обсуждались на примере или картинок, или таблиц. Если картинка и таблица должны находиться рядом, нужно воспользоваться командой\killfloatstyle
.
Например
произведёт следующий результат01:
\begin
{figure
}[!h]\CenterFloatBoxes
02:
\begin
{floatrow}03:
\ffigbox
[...]{\caption
{...}}{...}04:
%
05:
\
killfloatstyle
06:
%
07:
\ttabbox
[...]{\caption
{...}}{...}08:
\end
{floatrow}09:
\end
{figure
}
И всё-таки subfloats
Хотя во введении и было обещано не рассматривать вопросы,
связанные с расположением "подрисунков" (subfigures, subtables),
стоит отметить, что все вышеприведённые рецепты действуют и в их случае
с той лишь разницей, что надо использовать окружение
subfloatrow
вместо floatrow
.
Простой пример ниже демонстрирует это в деталях
Пара пунктов, на которые стоит обратить внимание:01:
\usepackage
{subcaption,floatrow,graphicx,calc}02:
\floatsetup
{floatrowsep=qquad}03:
...04:
\begin
{figure
}[!h]05:
\ffigbox
{06:
% объявляем, что будут 3 картинки в ряд
07:
\begin
{subfloatrow}[3]08:
\ffigbox
[\FBwidth
+1cm]{\caption
{My Caption left}}{\includegraphics
{...}}09:
\ffigbox
[\FBwidth
+1cm]{\caption
{My Caption mid...}}{\includegraphics
{...}}10:
\ffigbox
[\FBwidth
+1cm]{\caption
{My Caption right...}}{\includegraphics
{...}}11:
\end
{subfloatrow}12:
}13:
{% подпись ко всему float
14:
\caption
{Overall caption.}15:
}16:
\end
{figure
}
- надо загрузить дополнительно пакет
subcaption
; - вместо окружения
floatrow
используемsubfloatrow
; - причём помещаем его внутрь первого аргумента
\ffigbox
(строка 5); - а во втором аргументе
\ffigbox
помещаем подпись ко всему ряду рисунков (строка 14).
Абсолютно аналогично можно это применить и к таблицам,
заменив \ffigbox
на \ttabbox
Заключительный сложный пример для любознательных
Помимо рассмотренных выше трюков, floatrow
позволяет
создавать собственные типы float. Кроме того, пакет иеально функционирует
в тандеме с другим пакетом caption
, который позволяет
должным образом оформить подпись.
В следующем примере использованны эти возможности:
- Определен новый тип float под названием Photo (с собственным счётчиком и другими атрибутами), подпись которого набирается справа от картинки.
- Для таблиц и др. объектов, подпись отфoрмaтирована специальным образом.
01:
\usepackage
{caption,floatrow}02:
%------------------------------------------------
03:
% Форматируем подписи к таблицам, благодаря пакету caption
04:
\DeclareCaptionLabelFormat
{rightline}{\rightline
{\bothIfFirst
{#1}{ }#2}}05:
% метка Table справа, затем новая строка, метка наклонным, сама подпись жирным малым шрифтом
06:
\captionsetup
[table]{labelformat=rightline,labelsep=newline,%
07:
labelfont={md,sl},textfont={bf,small}}08:
% Подпись размещаем вверху от таблицы
09:
\floatsetup
[table]{style=Plaintop}10:
%-------------------------------------------------
11:
% Создаём новый тип float: photo
12:
% Команда \DeclareNewFloatType{тип}{опции} из пакета floatrow
13:
\DeclareNewFloatType
{photo}{name={Photo},placement=tbp}14:
% Определяем аналог \ffigbox для photo
15:
% с помощью \newfloatcommand{команда}{тип}[преамбула][ширина]
16:
\newfloatcommand
{photobox}{photo}%
17:
[{\capbeside
18:
\thisfloatsetup
{capbesideposition={right,bottom},% подпись справа внизу
19:
capbesidewidth=3cm}% ширина подписи 3см
20:
}]%
21:
[\FBwidth
]22:
% форматируем подпись с помощью пакета caption
23:
\captionsetup
[photo]{labelformat=rightline,labelsep=newline,%
24:
labelfont={md,sl},textfont={bf,small}}%
25:
%--------------------------------------------------
26:
% для обычного "Figure"
27:
\floatsetup
[figure]{capposition=bottom}28:
\captionsetup
[figure]{labelfont={md,sl},textfont={bf,small}}%
29:
%---------------------------------------------------
30:
...31:
\begin
{table}[!h]\CenterFloatBoxes
32:
\begin
{floatrow}33:
\ttabbox
[\FBwidth
]{\caption
{My Caption left}\label
{tab:1}}%
34:
{\begin
{tabular
}{c|c}35:
...36:
\end
{tabular
}37:
}38:
%
39:
\killfloatstyle
40:
%
41:
\photobox
{\caption
{Here goes a photo}\label
{ph:1}}{\includegraphics
{...}}42:
\end
{floatrow}43:
\end
{table}44:
45:
See Table~\ref
{tab:1} and Photo~\ref
{ph:1}. Also a ``normal'' Figure~\ref
{fig:1}.46:
47:
\begin
{figure
}[!h]48:
\ffigbox
{\caption
{Graph of a function}\label
{fig:1}}{\includegraphics
{...}}49:
\end
{figure
}
Подведение итогов
Пакет floatrow
позволяет не только автоматизировать
процесс расположения подписи
(сверху, снизу, сбоку от картинки), но и предоставляет
мощные средства для контроля над расположением объектов в ряд.
Предоставляемый им интерфейс облегчает форматирование визуального
материала и позволяет добиться желаемого результата без
больших затрат времени и сложных комбинаций с minipages.
Все примеры из данного поста могут быть найдены
здесь
и
здесь
в виде tex-файлов готовых к компиляции.
Документация к пакету
floatrow
доступна на
русском и
английском языках.
Пост выглядит круто, аж все Анонимусы разбежались и попрятались в страхе :-)
ОтветитьУдалитьЯ тут дизайню титульную страницу, и там надо разместить несколько рисунков в ряд. Поэтому у меня вопрос к тов. Amorua: есть ли у пакета floatrow какие-то конфликты с другими пакетами? У меня просто много пакетов включено.
@virens
ОтветитьУдалитьЕсли на титульной странице надо разместить много странного, не проще организовать какой-либо управляемый контейнер, да хоть окружение picture, и там уже располагать необходимые объекты с точностью до ангстрема?
@virens комментирует...
ОтветитьУдалитьПоэтому у меня вопрос к тов. Amorua: есть ли у пакета floatrow какие-то конфликты с другими пакетами?
Вроде, никаких конфликтов. floatrow замещает собой всю функциональность пакета float (включая наиболее используемую фичу [H])
Соглашусь с тов. Const, что при хитром размещении картинок на титульном листе, может оказаться проще использовать точное позиционирование, например, посредством tikz: что-то вроде
\begin{tikzpicture}
\node at (0,0){\includegraphics{картинка}};
\node at (1,0){\includegraphics{картинка}};
\end{tikzpicture}