编辑这个问题经过编辑并且变得更加精确。
背景
这个问题与我的另一个为了避免tcolorbox
那里描述的一些陷阱,我决定创建自己的框架绘制代码,灵感来自这个很好的答案。 它是主要优势与其他解决方案相比,它不会中断文本的正常流动,而是使用 TikZ 的overlay, remember picture
功能在背景中绘制所有内容。它适用于脚注与可拉伸垂直胶(与tcolorbox
所述相反这里)。
问题
我需要帮助指定框架垂直边距和填充的尺寸(含义类似于 CSS)。
考虑以下对象:
- 框架前的水平框的底部边缘,
- 框架的顶部边缘(由 的位置控制
\tikzmark
), - 框架内第一个水平框的顶部边缘,
- 框架内最后一个水平框的底部边缘,
- 框架的底部边缘(由 的位置控制
\tikzmark
), - 水平框的顶部边缘紧接着框架之后。
我希望将 (1) 和 (2) 之间的空间量精确地设置为\marginTop
,将 (2) 和 (3) 之间的空间量精确地设置为\paddingTop
,同样地,将 (4) 和 (5) 之间的空间量精确地设置为\paddingBottom
,最后将 (5) 和 (6) 之间的空间量精确地设置为\marginBottom
。
上述所有宏都在我的代码中定义,它们提供了一些粘合值。
鉴于我的代码(如下),这相当于\tikzmark
通过修改环境的代码将两个 s 放置在适当的位置tikzBgFrame
。怎么做呢?我尝试了许多方法,以各种方式组合\par
、\vskip
、\vspace
命令,但没有获得令人满意的结果。
此外,我将非常感激任何关于如何改进和更好地组织我的代码的反馈。
插图
代码
\documentclass{report}
\usepackage[utf8]{inputenc}
\usepackage{lipsum}
% \usepackage{lua-visual-debug} % only with luaTeX
\flushbottom
\setlength{\skip\footins}{10pt}
% --------------------------- %
% START of frame drawing code %
% --------------------------- %
\usepackage{tikz}
\usetikzlibrary{tikzmark,calc}
\usepackage{tikzpagenodes}
\usepackage{xassoccnt}
\usepackage{bophook}
\usepackage{xcolor}
\usepackage{ifthen}
% Colours
\definecolor{my-purple-very-light}{HTML}{f1ebf7}
\definecolor{my-purple}{HTML}{6700CE}
% Dimensions
\newcommand{\marginTop}{10pt}
\newcommand{\marginBottom}{10pt}
\newcommand{\marginFootnote}{10pt} % how to set this to \skip\footins?
\newcommand{\paddingHorizontal}{10pt}
\newcommand{\paddingTop}{5pt}
\newcommand{\paddingBottom}{5pt}
% Auxiliary ifs -- how to get rid of them?
\newif\ifHasBegin
\newif\ifHasEnd
% Get the "real" number of a page
\newcounter{realpage}
\DeclareAssociatedCounters{page}{realpage}
\AtBeginDocument{%
\stepcounter{realpage}
}
% Count frames
\newcounter{tikzbgframecounter}
\setcounter{tikzbgframecounter}{0}
\def\frametofinish{0}
% Redefine footnote to contain a tikzmark
\let\oldfootnoterule\footnoterule
\def\footnoterule{\tikzmark{footnotemark\therealpage}\oldfootnoterule}
% Things to do at begin of every page
\AtBeginPage{%
\setupAnchors% Add tikzmarks for the north west, and for the south east corners of the broken frames, taking footnotes into account
\drawContinuedFrame% Draw continued broken frame, if there is one
}
\newcommand{\setupAnchors}{
\begin{tikzpicture}[remember picture, overlay]
\tikzmark{frameNorthWestPage\therealpage}{([xshift=-\paddingHorizontal,yshift=\paddingTop]current page text area.north west)}
\coordinate (tmp1) at ([xshift=\paddingHorizontal,yshift=-\paddingBottom]current page text area.south east);
\iftikzmarkoncurrentpage{footnotemark\therealpage}% footnotes appear on this page
\coordinate (tmp2) at ([yshift=-\paddingBottom+\marginFootnote]pic cs:footnotemark\therealpage);
\tikzmark{frameSouthEastPage\therealpage}{(tmp2 -| tmp1)}
\else
\tikzmark{frameSouthEastPage\therealpage}{(tmp1)}
\fi
\end{tikzpicture}
}
% Frame types enum
\newcommand{\frameUnbroken}{0}
\newcommand{\frameFirst}{1}
\newcommand{\frameMiddle}{2}
\newcommand{\frameLast}{3}
% Draw a rectangle with a thick line on the left
\newcommand{\drawTikzBgFrame}[3][]{
\fill[my-purple-very-light,opacity=0.5] (#2) rectangle (#3);
\draw[my-purple, thick] ({#2}) -- ({#2} |- {#3});
}
% Draw the rectangle in an appropriate place, depending on the situation
\newcommand{\drawTikzBgFramePart}[2][\frameUnbroken]{%
\begin{tikzpicture}[remember picture, overlay]
\ifthenelse{#1=\frameUnbroken}{ % the frame is not broken, draw everything
\drawTikzBgFrame
{{pic cs:frameNorthWestPage\therealpage} |- {pic cs:frame#2begin}}
{{pic cs:frame#2end} -| {pic cs:frameSouthEastPage\therealpage}}
}{}
\ifthenelse{#1=\frameFirst}{ % draw the first part of a broken frame
\drawTikzBgFrame
{{pic cs:frameNorthWestPage\therealpage} |- {pic cs:frame#2begin}}
{pic cs:frameSouthEastPage\therealpage}
}{}
\ifthenelse{#1=\frameMiddle}{ % draw the middle part of a broken frame
\drawTikzBgFrame
{pic cs:frameNorthWestPage\therealpage}
{pic cs:frameSouthEastPage\therealpage}
}{}
\ifthenelse{#1=\frameLast}{ % draw the final part of a broken frame
\drawTikzBgFrame
{pic cs:frameNorthWestPage\therealpage}
{{pic cs:frame#2end} -| {pic cs:frameSouthEastPage\therealpage}}
}{}
\end{tikzpicture}%
}
% Main part - an environment for placing frames
\newenvironment{tikzBgFrame}[1][]{{%
\parskip=0pt%
\par\stepcounter{tikzbgframecounter}%
\strut\tikzmark{frame\thetikzbgframecounter begin}\par%
\iftikzmarkoncurrentpage{frame\thetikzbgframecounter end}{%
\drawTikzBgFramePart[\frameUnbroken]{\thetikzbgframecounter}%
}\else{%
\drawTikzBgFramePart[\frameFirst]{\thetikzbgframecounter}%
\gdef\frametofinish{\thetikzbgframecounter}% schedule drawing of subsequent parts, handled in \drawContinuedFrame
}\fi%
\ignorespaces%
}}{{%
\parskip=0pt%
\par\strut\tikzmark{frame\thetikzbgframecounter end}\par%
\ignorespacesafterend}}
% Check whether some frame needs to be continued, draw them in the background
\newcommand{\drawContinuedFrame}{
\ifthenelse{\not\equal{\frametofinish}{0}}{
\iftikzmarkoncurrentpage{frame\frametofinish begin}\HasBegintrue\else\HasBeginfalse\fi
\iftikzmarkoncurrentpage{frame\frametofinish end}\HasEndtrue\else\HasEndfalse\fi
\ifthenelse{\boolean{HasBegin}}{}{
\ifthenelse{\not\boolean{HasEnd}}{
\drawTikzBgFramePart[\frameMiddle]{\frametofinish}
}{
\drawTikzBgFramePart[\frameLast]{\frametofinish}
\gdef\frametofinish{0} % frame has ended, stop drawing on subsequent pages
}
}
}{}
}
% ------------------------- %
% END of frame drawing code %
% ------------------------- %
% Frame drawing test follows
\begin{document}
\newcommand{\object}{\par\noindent\tikz[]{\draw (0,0) rectangle (\textwidth-0.4pt,3); \node at (\textwidth/2,1.5) {Content}}\par}
\section{Introduction}
% \ifthenelse{\equal{\token}{\token}}{true}{false}
\lipsum[1]
\begin{tikzBgFrame}
\lipsum[1-2][1-5]
\end{tikzBgFrame}
\begin{tikzBgFrame}
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus eleifend mauris vitae consectetur\footnote{This is a footnote.} dapibus. Curabitur sollicitudin quam eget convallis rutrum. Pellentesque pulvinar augue
\object
\smallskip
\object
\medskip
\object
\medskip
\object
\medskip
\lipsum[5]
Another footnote is referenced here\footnote{This is another footnote\dots}, and here\footnote{\dots and the third one.} too.
\lipsum[6]
\medskip
\object
\medskip
\object
\medskip
\object
\medskip
\object
\end{tikzBgFrame}
\end{document}