tcolorbox 的替代品-如何指定垂直跳过?

tcolorbox 的替代品-如何指定垂直跳过?

编辑这个问题经过编辑并且变得更加精确。

背景

这个问题与我的另一个为了避免tcolorbox那里描述的一些陷阱,我决定创建自己的框架绘制代码,灵感来自这个很好的答案。 它是主要优势与其他解决方案相比,它不会中断文本的正常流动,而是使用 TikZ 的overlay, remember picture功能在背景中绘制所有内容。它适用于脚注可拉伸垂直胶(与tcolorbox所述相反这里)。

问题

我需要帮助指定框架垂直边距和填充的尺寸(含义类似于 CSS)。

考虑以下对象:

  1. 框架前的水平框的底部边缘,
  2. 框架的顶部边缘(由 的位置控制\tikzmark),
  3. 框架内第一个水平框的顶部边缘,
  4. 框架内最后一个水平框的底部边缘,
  5. 框架的底部边缘(由 的位置控制\tikzmark),
  6. 水平框的顶部边缘紧接着框架之后。

我希望将 (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}

链接至 Overleaf(来源和预览)

关联

相关内容