最好的方法是使用一种样式。
手动至少有三种方法可以获得填充的包装纸:
\documentclass[11pt]{scrartcl}
\usepackage{tikz}
\usetikzlibrary{ fit,backgrounds, calc,scopes}
\begin{document}
\begin{tikzpicture}[x=2 cm,y=2 cm]
\node[draw,fill=blue!20] (s){start};
\node[draw,fill=green!20] (e) at (2,1){end};
\begin{scope}[on background layer]
\node[rounded corners,
fill=lightgray!50,
inner sep = 4ex,
fit=(s)(e),
label=above:Wrapper] {};
\end{scope}%
\end{tikzpicture}
\begin{tikzpicture}[scale=2]
\node[draw,fill=blue!20] (s){start};
\node[draw,fill=green!20] (e) at (2,1){end};
\begin{scope}[on background layer]
\fill[rounded corners,
red!20] ($(s.south west)+(-2ex,-2ex)$) rectangle ($(e.north east)+(2ex,2ex)$)
coordinate [pos=0.5] (ce)
coordinate [pos=1] (ne)
(ce |- ne) coordinate (no) ;
\node [above] at (no) {Wrapper} ;
\end{scope}%
\end{tikzpicture}
\begin{tikzpicture}[scale=2]
{ [local bounding box= box]
\node[draw,fill=blue!20] (s){start};
\node[draw,fill=green!20] (e) at (2,1){end}; }
\begin{scope}[on background layer]
\fill[rounded corners,
red!20] ($(box.south west)+(-2ex,-2ex)$) rectangle ($(box.north east)+(2ex,2ex)$)
coordinate [pos=0.5] (ce)
coordinate [pos=1] (ne)
(ce |- ne) coordinate (no) ;
\node [above] at (no) {Wrapper} ;
\end{scope}%
\end{tikzpicture}
\end{document}
你会得到
自动地
我做了一些尝试
\documentclass[11pt]{scrartcl}
\usepackage{tikz}
\usetikzlibrary{fit,backgrounds,calc}
\tikzset{add reference/.style={insert path={%
coordinate [pos=0,xshift=-0.5\pgflinewidth,yshift=-0.5\pgflinewidth] (#1 south west)
coordinate [pos=1,xshift= 0.5\pgflinewidth,yshift= 0.5\pgflinewidth] (#1 north east)
coordinate [pos=.5] (#1 center)
(#1 south west |- #1 north east) coordinate (#1 north west)
(#1 center |- #1 north east) coordinate (#1 north)
(#1 center |- #1 south west) coordinate (#1 south)
(#1 south west -| #1 north east) coordinate (#1 south east)
(#1 center -| #1 south west) coordinate (#1 west)
(#1 center -| #1 north east) coordinate (#1 east)
}}}
\tikzset{wrapper/.style={%
append after command={%
($(\tikzlastnode.south west)+(-#1,-#1)$)
rectangle
($(\tikzlastnode.north east)+(#1,#1)$)[add reference=R]
}}}
\begin{document}
\begin{enumerate}
\item \begin{tikzpicture}
\draw[fill=red!50,label distance=.5cm]
node[label=90:Wrapper,
draw,
fill=blue!30,
wrapper={.5cm}] at (2,3) {Inside} ;
\end{tikzpicture}
\item \begin{tikzpicture}
\draw[fill=red!50]
node[wrapper={.5cm},
draw,
fill=blue!30] at (2,3) {Inside} ;
\node[above,align=center] at (R north){Wrapper};
\end{tikzpicture}
\item \begin{tikzpicture} [wrapper/.style ={append after command={%
node[inner sep=#1,
draw,
fit=(\tikzlastnode),
fill=lightgray!50,
fill opacity=.5](tw){}}}]
\node[wrapper={4ex},draw,fill=blue!30,text=black] {Inside} ;
\node[above] at (tw.north) {Wrapper} ;
\end{tikzpicture}
\item \begin{tikzpicture} [wrapper/.style 2 args={%
insert path={%
\pgfextra{%
\begin{scope}[on background layer]
\node[inner sep = #1,
draw,
fit=(#2),
fill = red!30] (tw){};
\end{scope}}}}]
\node[draw,fill=blue!30,text=black] (a) {Inside} ;
\node[wrapper={4ex}{a},above] at (tw.north) {Wrapper} ;
\end{tikzpicture}
\item \begin{tikzpicture} [wrapper/.style 2 args={%
execute at end scope={
insert path={%
\pgfextra{%
\begin{scope}[on background layer]
\node[inner sep = #1,
draw,
fit=#2,
fill = red!30](tw){};
\end{scope}}}}}]
\begin{scope}[wrapper={4ex}{(s)(e)}]
\node[draw,fill=blue!30] (s) {start};
\node[draw,fill=green!30] (e) at (2,1) {end};
\end{scope}
\node[above] at (tw.north) {Wrapper} ;
\end{tikzpicture}
\end{enumerate}
\end{document}
我得到了
我的问题是:如何获得更简单的东西?
在情况 1 中,我需要使用label distance=.5cm
,它不太优雅。我需要指定两个值。
在情况 2 中,我需要使用,add reference/.style
而且它很复杂。
在情况 3 中,我尝试用节点替换矩形,但正如您所见,存在问题。
在案例 4 中,我尝试用节点替换矩形,但我需要两条线才能得到结果,而且我认为我需要更多参数。我不喜欢使用 (tw)。
在最后一种情况 5 中,我尝试使用一组节点。这里我需要在参数中指定节点,但很难避免这一点。我不喜欢使用 (tw)。
答案1
我不太清楚你到底想要什么。下面从你的几次尝试中选取元素,并将它们组合成我认为非常简约且灵活的内容:
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{fit,backgrounds}
\begin{document}
\begin{tikzpicture}[
wrapper/.style 2 args={%
local bounding box=localbb,
execute at end scope={
\begin{scope}[on background layer]
\node[inner sep = #1,
draw,
fit=(localbb),
fill = red!30,
label = {above:#2}
]{};
\end{scope}}}]
\begin{scope}[wrapper={4ex}{Wrapper}]
\node[draw,fill=blue!30] (s) {start};
\node[draw,fill=green!30] (e) at (2,1) {end};
\end{scope}
\end{tikzpicture}
\end{document}
我能想到的唯一缺点是,这种方式无法嵌套包装器。为此,您必须以不同的方式命名边界框。
您可能还对以下问题感兴趣TikZ:在范围或图片的末尾执行代码并访问其边界框。
这是一个更精美的版本,允许嵌套(除了内框不影响外框的大小)。所有包装框都在最后绘制,以便它们按预期顺序出现。抱歉,\noexpand
s 的数量太多了。我想不出更好的方法来及时修复本地边界框的计数。
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{fit,backgrounds}
\makeatletter
\newcount\tsx@wrapperdepth
\tsx@wrapperdepth=0
\newcount\tsx@wrappercount
\tsx@wrappercount=0
\gdef\tsx@wrappercode{}
\tikzset{wrap/.style={
local bounding box/.expanded={localbb\number\tsx@wrappercount},
execute at begin scope={
\global\advance\tsx@wrapperdepth by 1\relax
\global\advance\tsx@wrappercount by 1\relax},
execute at end scope/.expanded={
\noexpand\global\noexpand\advance\noexpand\tsx@wrapperdepth by -1\noexpand\relax
%
% store the wrapper drawing code for later use
\noexpand\toks@\noexpand\expandafter{\noexpand\tsx@wrappercode}
\noexpand\xdef\noexpand\tsx@wrappercode{%
\noexpand\noexpand\noexpand\node[fit=(localbb\number\tsx@wrappercount),
every wrap,
#1
]{};
\noexpand\the\noexpand\toks@
}
%
% if we are at depth 0, draw all the wrappers
\noexpand\ifnum\noexpand\tsx@wrapperdepth=0
\noexpand\begin{scope}[on background layer]
\noexpand\tsx@wrappercode
\noexpand\end{scope}
\noexpand\gdef\noexpand\tsx@wrappercode{}
\noexpand\fi
}}
}
\tikzset{every wrap/.style={draw, fill=red!30}}
\makeatother
\begin{document}
\begin{tikzpicture}
\begin{scope}[wrap={label={below:a big box}}]
\node[draw,fill=blue!30] at (0,0) {start 1};
\begin{scope}[wrap={label={above:a small box}, inner sep=2ex,fill=black!30}]
\node[draw,fill=blue!30] at (2,1) {start 2};
\node[draw,fill=green!30] at (3,2) {end 2};
\end{scope}
\node[draw,fill=green!30] at (4,4) {end 1};
\end{scope}
\end{tikzpicture}
\end{document}
答案2
这是一个部分可运行的示例。见下文。
语法命令相对方便。假设我们需要一个装饰矩形中的 4 个节点。我们首先声明一个,然后将所有应该位于其上方(或其中)的节点放在其中。在最后一个节点选项中,我们使用一些特定的输入和由 指定的一些外部 sep 值来\draw[options]
触发我们的自制风格。第一个坐标是左下角的坐标。wrap
with padding x cm
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{decorations.pathmorphing}
\begin{document}
\begin{tikzpicture}[
wrap/.style args={#1 and #2 with padding #3}{
append after command={
([shift={(-#3,-#3)}]#1) rectangle ([shift={(#3,#3)}]#2)
}
}
]
\node (D) at (2,0) {painted}; %Behind the wrapper
\draw[fill=blue!50,decoration=zigzag,decorate]% <-- Add this ,opacity=0.1
%Regular nodes
node[draw,rounded corners,fill=red] at (2,2) (A) {bar}
node[draw=blue,dashed,thick,fill=yellow!60,align={center}] at (1,1) (C) {Not painted\\over}
node[align=center] at (0.3cm,2.1cm) (E) {Nodding\\Here}
%Last one wraps
node [draw,thick,wrap=B and A with padding 1cm] at (0,0) (B) {foo};
\end{tikzpicture}
\end{document}
包装器后面有一个隐藏节点,用于测试它是否按预期工作。当您更改矩形的不透明度选项时,您应该能够看到它。包装器不透明度由内部节点继承,我还没有看到快速修复方法。有些选项没有被继承,但不透明度(可能还有其他一些)似乎是继承的。同时,我会尝试了解原因。如果您看到修复,请告诉我。