原始答案

原始答案

根据我关于尺寸的问题中非常巧妙的答案tcolorbox

使用 \tcbsetmacrotoheightofnode 和 tcolorbox 中的维度

我想进行改进,使我的宏更美观。我解释一下:在我最初的问题中,我想使用标题节点的高度,而不是其宽度,因为宽度是固定的……在最初的问题中为 .8cm。

现在我想根据标题的长度使框的宽度也可变。我可以通过使用命令来做到这一点,这要感谢对我的帖子答案的评论,text width=width("#1")我对此有两个问题:

  1. 此命令给出了合适的内容,但框未围绕标题居中。我怎样才能使其居中?

  2. 现在我想将标题放在与标题框之间的固定距离(例如 1 毫米)上,因此请使用标题框的宽度,就像使用其高度一样。我们可以使用第三个参数来执行此操作,使用以下命令:

    attach boxed title to top right={%
            xshift=#3,yshift=- \tcboxedtitleheight+.5mm},`
    

    其中#3将类似于\mywidth+2mm,通过类似的高度命令获得...... \tcbsetmacrotowidthofnode\mywidth{tmpbox}

现在我知道我不能使用像 这样的命令\tcbset{mystyle/.style 2 args来处理两个以上的参数,在这种情况下,我的想法是我们必须使用像 这样的命令\DeclareTColorBox,而不是\newtcolorbox,但我还没有成功实现它。请问有什么有用的答案吗?非常感谢。

我给出使用的.tex 文件:

\documentclass{book}

\usepackage[most]{tcolorbox}
\usepackage{varwidth}
\tcbuselibrary{skins,breakable}

%\usepackage{polyglossia}
%\setmainlanguage{english}

\newcommand{\myboxnode}[2]{%
\node[fill=#2!5!white, draw=#2!75!black, line width=.5pt, 
    below left, minimum height=2em, 
   text width=width("#1"), align=center,
   font=\bfseries] (tmpbox) at ([xshift=13.5mm,yshift=-1mm]frame.north east) {#1 \thetcbcounter}}

\tcbset{
    mystyle/.style 2 args={
        enhanced jigsaw, breakable, 
        colback=white, colframe=white, 
        sharp corners, 
        boxrule = 0mm, 
        top=2mm, bottom=2mm, left=2mm, right=2mm,
%       varwidth boxed title,
        tikznode boxed title={minimum width=\textwidth/4-15mm-4.5mm},
        attach boxed title to top right={%
            xshift=.5mm,yshift=- \tcboxedtitleheight+.5mm},
        boxed title style={%
            enhanced,
            sharp corners, 
            colframe=#1!75!black, 
            left=1mm, right=1mm,
            boxrule=.5mm},
        colbacktitle=#1!5!white, 
        coltitle=black,
        extrude right by=-15mm,
        underlay unbroken and first={%
            \myboxnode{#2}{#1};
            \tcbsetmacrotoheightofnode\myheight{tmpbox}
            \draw [#1!75!black,line width=.5mm]
              ([shift={(15mm-.5\pgflinewidth, -\myheight+.5\pgflinewidth)}]frame.north east) |- 
              ([shift={(-\textwidth/4+15mm,+.5\pgflinewidth)}]frame.north east);
            \draw [#1!75!black,line width=.5mm]
              ([shift={(.5\pgflinewidth,-\myheight+.5\pgflinewidth)}]frame.north west) |-
              ([shift={(\textwidth/4,+.5\pgflinewidth)}]frame.north west);

           \draw [#1!75!black,line width=.5mm] ([yshift=.25mm]frame.south west)(\textwidth/4,0) -- (0,0);
           \draw [#1!75!black,line width=.5mm] ([xshift=.25mm,yshift=.25mm]frame.south west) -- +(0,\myheight);
           \draw [#1!75!black,line width=.5mm] ([xshift=14.75mm,yshift=.25mm]frame.south east) -- +(0,\myheight);
           \draw [#1!75!black,line width=.5mm] ([yshift=.25mm]frame.south east)(3*\textwidth/4,0) -- (\textwidth,0);
         },
    },
    mytitle/.style 2 args={
        code={%
            \ifstrempty{#1}
            {\tcbset{
                before upper={\parshape 4
                    0pt \dimexpr \hsize-14mm\relax
                    0pt \dimexpr \hsize-14mm\relax
                    0pt \dimexpr \hsize-14mm\relax
                    0pt \hsize}}}
            {\tcbset{
                title={#1},
                before upper={\vspace*{\baselineskip}\parshape 3
                    0pt \dimexpr \hsize-14mm\relax
                    0pt \dimexpr \hsize-14mm\relax
                    0pt \hsize},
                underlay unbroken and last={
                    \draw [#2!75!black,line width=.5mm](frame.south east)--++(180:\tcboxedtitlewidth-\pgflinewidth);
                }}}
        },
    }
}

\newtcolorbox[auto counter]{proposition}[2][]{%
    mystyle={blue}{Prop},
    mytitle={#2}{blue},
    #1}

\newtcolorbox[auto counter]{definition}[2][]{%
    mystyle={green}{Def},
    mytitle={#2}{green},
    #1}

\begin{document}
\pagestyle{empty}

\begin{definition}{}
A non-titled definition
\vspace{2.2cm}
\end{definition}

\begin{proposition}{A long title}
A titled proposition
\vspace{2cm}
\end{proposition}

\begin{definition}[height=2cm,label=Exlab]{A}
A titled definition
\end{definition}
\ref{Exlab}
\end{document}

并使用 xelatex 进行编译:

在此处输入图片描述

答案1

根据一些评论,这里或多或少是完全重写。它还考虑了框中可能出现的分页符(因为breakable样式中确实有分页符),方法是在 中绘制顶角underlay unbroken and first,在 中绘制底角underlay unbroken and last

\node我所做的更改之一是使用 中的手动添加标题。据我所知,underlay unbroken and first这一更改使得 变得不必要,从而使得这里和那里的所有 15 毫米调整都变得不必要。extrude right by

这样做还使得标题的定位更容易,因为它可以相对于tmpboxframe节点放置。

我还删除了mytitle样式,而是添加了第四个参数,mystyle即标题。 parshape 所需的内容被移动到set parshape/.code

\documentclass{book}
\usepackage{lipsum}

\usepackage[most]{tcolorbox}
\usetikzlibrary{calc} % for the let-syntax    

\tcbuselibrary{skins,breakable}

%\usepackage{polyglossia}
%\setmainlanguage{english}

\newlength\LineW
\setlength\LineW{0.5mm}
\tikzset{
  frameline/.style={
    draw=#1!75!black,line width=\LineW
  }
}

\newcommand{\myboxnode}[2]{%
\node[
   fill=#2!5!white, draw=#2!75!black, line width=.5pt, 
   below left, minimum height=2em, 
   text width=width("#1")*1.2,
   align=center,
   font=\bfseries
   ] (tmpbox) at 
     ([xshift=-1mm-0.5\LineW,yshift=-1mm-0.5\LineW]frame.north east)
   {#1 \thetcbcounter}}

\tcbset{
    mystyle/.style n args={4}{
        enhanced jigsaw,
        breakable, 
        colback=white,
        opacityframe=0,
        top=2mm, bottom=2mm,
        left=2mm, right=2mm,
        % drawing corners on top and title
        underlay unbroken and first={%
            \myboxnode{#2}{#1};
            \tcbsetmacrotoheightofnode\HHH{tmpbox}
            % \global\let so it's available outside the underlay unbroken and first
            \global\let\myheight\HHH
            % 
            \ifstrempty{#4}{ % if no title
                % draw top right frame
                \draw [frameline={#1}]
                      ([shift={(0, -\myheight)}]frame.north east) |- 
                      ([shift={(-\textwidth/4,0)}]frame.north east);
            }{ % if title
                % add node with title
                \node [anchor=north east,
                       inner xsep=2mm,
                       fill=#1!5!white,
                       frameline={#1}
                      ]
                     (titlenode)
                     at
                     ([xshift=-#3,yshift=0.5\pgflinewidth]frame.north -| tmpbox.west)
                     {#4};

                % draw top right frame
                \draw [frameline={#1}]
                      ([yshift=-0.5\pgflinewidth]titlenode.north east) -|
                      ([yshift=-\myheight]frame.north east);

                % calculate distance from corner of frame to opposite corner of title
                % save in \mywidth
                \path let \p1=(frame.north east), \p2=(titlenode.north west), \n1={\x1-\x2} in
                    \pgfextra{\pgfmathsetlengthmacro{\WWW}{\n1}\global\let\mywidth\WWW}
                ;
            }
            % draw top left frame
            \draw [frameline={#1}]
                  ([shift={(0,-\myheight)}]frame.north west) |-
                  ([shift={(\textwidth/4,0)}]frame.north west);

        },
        % if box breaks across pages, draw corners on last part
        underlay unbroken and last={%
            \ifstrempty{#4}{ % if no title
                % draw bottom right frame
                \draw [frameline={#1}]
                      ([shift={(0, \myheight)}]frame.south east) |- 
                      ([shift={(-\textwidth/4,0)}]frame.south east);
            }{
                % draw bottom right frame
                \draw [frameline={#1}]
                      ([xshift=-\mywidth]frame.south east) -|
                      ([yshift=\myheight]frame.south east);
            }
            % draw bottom left frame
            \draw [frameline={#1}]
                  ([yshift=\myheight]frame.south west) |- 
                  ([xshift=\textwidth/4]frame.south west);
        },
        set parshape/.code={%
            % 0.666em is twice the inner sep
            % 6mm is 2mm from left, 2mm from right, 1mm right of box, 1mm left of box
            \pgfmathsetlengthmacro{\parwidth}{\hsize-(width("#2")*1.2+0.666em+6mm)}
            \ifstrempty{##1}
            {\tcbset{
                before upper={\parshape 4
                    0pt \parwidth
                    0pt \parwidth
                    0pt \parwidth
                    0pt \hsize}
                    }
            }
            {\tcbset{
                before upper={\vspace*{\baselineskip}\parshape 3
                    0pt \parwidth
                    0pt \parwidth
                    0pt \hsize},
             }}
        },
       set parshape={#4}
  }
}

\newtcolorbox[auto counter]{proposition}[2][]{%
    mystyle={blue}{Prop}{1mm}{#2},
    #1}

\newtcolorbox[auto counter]{definition}[2][]{%
    mystyle={green}{Def}{1mm}{#2},
    #1}

\begin{document}
\pagestyle{empty}

\begin{definition}{}
\lipsum[1]
\end{definition}

\begin{proposition}{A long title}
\lipsum[1]
\end{proposition}

\begin{definition}[height=2cm,label=Exlab]{A}
A titled definition
\end{definition}
\ref{Exlab}

\begin{definition}{A}
 A long titled definition
\lipsum[3-4]
\end{definition}

\end{document}

上述代码的输出

原始答案

我认为这至少可以解释部分原因。

你可以使用以下方式为一个样式指定 2 个以上的参数

mystyle/.style n args={n}{<style definition>}

所以下面我使用了

mystyle/.style n args={3}{...

为了获得适当的偏移量(至少粗略地),我添加了以下内容mystyle

        titleshift/.code 2 args={%
         % * width("##1")*1.2 is same as used in\myboxnode
         % * but ##1 refers to the first argument passed to the titleshift key
         % * double ## required because #1 would refer to the first argument
         %   passed to mystyle
         % * ##2 is the second argument passed to titleshift, which is the third
         %   argument passed to mystyle 
         % * +0.5pt is the line width of \myboxnode
         % * -11mm looks OK, but I'm not entirely sure why that value is required
         %   It's the "extrude right by"-value minus 4mm-ish
         \pgfmathsetlengthmacro{\titlexshift}{width("##1")*1.2+##2+0.5pt-11mm}
        },
        % use the titleshift key, which will set the \titlexshift macro
        titleshift={#2}{#3},

第一部分定义了一个titleshift接受两个参数的键。.code处理程序评估其中的代码,这里使用 定义了一个长度宏\pgfmathsetlengthmacro{\titlexshift}{width("##1")*1.2+##2+0.5pt-11mm}。(有关解释,请参阅上面的注释。)当将键与 一起使用时titleshift={#2}{#3},它会将传递给 的第二个和第三个参数mystyle作为输入。

而且因为mystyle现在有三个强制参数,所以您必须使用mystyle={blue}{Prop}{1mm}而不是mystyle={blue}{Prop}

代码输出

\documentclass{book}

\usepackage[most]{tcolorbox}
\usepackage{varwidth}
\tcbuselibrary{skins,breakable}

%\usepackage{polyglossia}
%\setmainlanguage{english}

\newcommand{\myboxnode}[2]{%
\node[fill=#2!5!white, draw=#2!75!black, line width=.5pt, 
    below left, minimum height=2em, 
   text width=width("#1")*1.2, align=center,
   font=\bfseries] (tmpbox) at ([xshift=13.5mm,yshift=-1mm]frame.north east) {#1 \thetcbcounter}}

\tcbset{
    mystyle/.style n args={3}{
        enhanced jigsaw, breakable, 
        colback=white, colframe=white, 
        sharp corners, 
        boxrule = 0mm, 
        top=2mm, bottom=2mm, left=2mm, right=2mm,
%       varwidth boxed title,
        tikznode boxed title={minimum width=\textwidth/4-15mm-4.5mm},
        titleshift/.code 2 args={%
         % * width("##1")*1.2 is same as used in\myboxnode
         % * but ##1 refers to the first argument passed to the titleshift key
         % * double ## required because #1 would refer to the first argument
         %   passed to mystyle
         % * ##2 is the second argument passed to titleshift, which is the third
         %   argument passed to mystyle 
         % * +0.5pt is the line width of \myboxnode
         % * -11mm looks OK, but I'm not entirely sure why that value is required
         %   It's the "extrude right by"-value minus 4mm-ish
         \pgfmathsetlengthmacro{\titlexshift}{width("##1")*1.2+##2+0.5pt-11mm}
        },
        % use the titleshift key, which will set the \titlexshift macro
        titleshift={#2}{#3},
        attach boxed title to top right={%
            xshift=-\titlexshift,yshift=- \tcboxedtitleheight+.5mm},
        boxed title style={%
            enhanced,
            sharp corners, 
            colframe=#1!75!black, 
            left=1mm, right=1mm,
            boxrule=.5mm},
        colbacktitle=#1!5!white, 
        coltitle=black,
        extrude right by=-15mm,
        underlay unbroken and first={%
            \myboxnode{#2}{#1};
            \tcbsetmacrotoheightofnode\myheight{tmpbox}
            \draw [#1!75!black,line width=.5mm]
              ([shift={(15mm-.5\pgflinewidth, -\myheight+.5\pgflinewidth)}]frame.north east) |- 
              ([shift={(-\textwidth/4+15mm,+.5\pgflinewidth)}]frame.north east);
            \draw [#1!75!black,line width=.5mm]
              ([shift={(.5\pgflinewidth,-\myheight+.5\pgflinewidth)}]frame.north west) |-
              ([shift={(\textwidth/4,+.5\pgflinewidth)}]frame.north west);

           \draw [#1!75!black,line width=.5mm] ([yshift=.25mm]frame.south west)(\textwidth/4,0) -- (0,0);
           \draw [#1!75!black,line width=.5mm] ([xshift=.25mm,yshift=.25mm]frame.south west) -- +(0,\myheight);
           \draw [#1!75!black,line width=.5mm] ([xshift=14.75mm,yshift=.25mm]frame.south east) -- +(0,\myheight);
           \draw [#1!75!black,line width=.5mm] ([yshift=.25mm]frame.south east)(3*\textwidth/4,0) -- (\textwidth,0);
         },
    },
    mytitle/.style 2 args={
        code={%
            \ifstrempty{#1}
            {\tcbset{
                before upper={\parshape 4
                    0pt \dimexpr \hsize-14mm\relax
                    0pt \dimexpr \hsize-14mm\relax
                    0pt \dimexpr \hsize-14mm\relax
                    0pt \hsize}}}
            {\tcbset{
                title={#1},
                before upper={\vspace*{\baselineskip}\parshape 3
                    0pt \dimexpr \hsize-14mm\relax
                    0pt \dimexpr \hsize-14mm\relax
                    0pt \hsize},
                underlay unbroken and last={
                    \draw [#2!75!black,line width=.5mm](frame.south east)--++(180:\tcboxedtitlewidth-\pgflinewidth);
                }}}
        },
    }
}

\newtcolorbox[auto counter]{proposition}[2][]{%
    mystyle={blue}{Prop}{1mm},
    mytitle={#2}{blue},
    #1}

\newtcolorbox[auto counter]{definition}[2][]{%
    mystyle={green}{Def}{1mm},
    mytitle={#2}{green},
    #1}

\begin{document}
\pagestyle{empty}

\begin{definition}{}
A non-titled definition
\vspace{2.2cm}
\end{definition}

\begin{proposition}{A long title}
A titled proposition
\vspace{2cm}
\end{proposition}

\begin{definition}[height=2cm,label=Exlab]{A}
A titled definition
\end{definition}
\ref{Exlab}
\end{document}

相关内容