如何自动在节点或一组节点周围绘制一个填充的包装器?

如何自动在节点或一组节点周围绘制一个填充的包装器?

最好的方法是使用一种样式。

手动至少有三种方法可以获得填充的包装纸:

\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:在范围或图片的末尾执行代码并访问其边界框


这是一个更精美的版本,允许嵌套(除了内框不影响外框的大小)。所有包装框都在最后绘制,以便它们按预期顺序出现。抱歉,\noexpands 的数量太多了。我想不出更好的方法来及时修复本地边界框的计数。

\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]触发我们的自制风格。第一个坐标是左下角的坐标。wrapwith 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}

在此处输入图片描述

包装器后面有一个隐藏节点,用于测试它是否按预期工作。当您更改矩形的不透明度选项时,您应该能够看到它。包装器不透明度由内部节点继承,我还没有看到快速修复方法。有些选项没有被继承,但不透明度(可能还有其他一些)似乎是继承的。同时,我会尝试了解原因。如果您看到修复,请告诉我。

相关内容