根据我关于尺寸的问题中非常巧妙的答案tcolorbox
,
使用 \tcbsetmacrotoheightofnode 和 tcolorbox 中的维度
我想进行改进,使我的宏更美观。我解释一下:在我最初的问题中,我想使用标题节点的高度,而不是其宽度,因为宽度是固定的……在最初的问题中为 .8cm。
现在我想根据标题的长度使框的宽度也可变。我可以通过使用命令来做到这一点,这要感谢对我的帖子答案的评论,text width=width("#1")
我对此有两个问题:
此命令给出了合适的内容,但框未围绕标题居中。我怎样才能使其居中?
现在我想将标题放在与标题框之间的固定距离(例如 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
这样做还使得标题的定位更容易,因为它可以相对于tmpbox
和frame
节点放置。
我还删除了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}