我想绘制类似以下(photoshop 的)渲染效果:
此图像由三个 s 组成\node
,每个 s 使用不同的边框。整个图像固定在 上chain
,因为在我的实际情况中,我正在创建类似TikZ 教程中的语法图(p60)。
现在,我有一个 MWE,它可以渲染 L、C 和 R 之间的边界\node
,但我希望它们消失而不改变“外部”边界。
我的实际代码:
\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{chains,scopes,shapes.misc}
\begin{document}
\begin{tikzpicture}[start chain,
node distance=5mm,
every node/.style={on chain},
connect/.style={join=by ->},
point/.style={coordinate},
l/.style={draw, fill=cyan!50, rounded rectangle, rounded rectangle right arc=0},
c/.style={draw, fill=green!50},
r/.style={draw, fill=orange!50, rounded rectangle, rounded rectangle left arc=0},
cozy/.style={node distance=-\pgflinewidth}]
\node[point] (p1) {};
\node [l, connect] (l) {L};
{[cozy]
\node [c] (c) {C};
\node [r] (r) {R};
}
\node[point, connect] (p2) {};
\end{tikzpicture}
\end{document}
自定义边框(修订版)
我已经关注这个例子,@Harish Kumar的回答, 和这个答案。我尝试手动绘制边框,对形状的每个部分使用略有不同的方法。它们都有各自的缺点:
- 应用于L:将 保留为默认值 (
\node
) ,将导致包含宽度为 的周围空间。为了在的尺寸内绘制边框,边框不得超出此空间。不幸的是,边框内部的一部分绘制在填充物后面,使其看起来太窄。此外,东部锚点现在看起来好像有点偏离。line width
\pgflinewidth
draw=none
\node
0.5*\pgflinewidth
\node
- 应用于C:设置至少
\node
可以line width=0
确保所有锚点(尤其是东部和西部)都处于正确的位置。但是,这样一来,整个边框都会绘制在填充物后面。 - 应用于 R:设置
\node
,line width=0
并绘制边框外部填充物。这会导致边框超出\node
的尺寸,使其与连接对象重叠。
\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{calc,chains,scopes,shapes.misc,backgrounds}
\pgfdeclarelayer{background}
\pgfdeclarelayer{foreground}
\pgfdeclarelayer{foreforeground}
\pgfsetlayers{background,main,foreground,foreforeground}
\begin{document}
\begin{tikzpicture}[start chain,
node distance=5mm,
every node/.style={on chain},
connect/.style={join=by ->},
point/.style={coordinate},
l/.style={line width=\pgflinewidth, fill=cyan!50, rounded rectangle, rounded rectangle right arc=0, append after command={% <= for the border
\pgfextra{\begin{pgfinterruptpath}\begin{pgfonlayer}{foreground}
\draw[] let \p1=($(\tikzlastnode.north east)+(-0.5\pgflinewidth,-0.5\pgflinewidth)$),
\p2=($(\tikzlastnode.north west)+(0,-0.5\pgflinewidth)$),
\p3=($(\tikzlastnode.south west)+(0,0.5\pgflinewidth)$),
\p4=($(\tikzlastnode.south east)+(-0.5\pgflinewidth,0.5\pgflinewidth)$),
\n1={0.5*(\y2-\y3)} in
(\p1) -- (\p2) arc(90:270:\n1) -- (\p4);
\end{pgfonlayer}\end{pgfinterruptpath}}
}},
c/.style={line width=0, fill=green!50, append after command={% <= for the border
\pgfextra{%
\begin{pgfinterruptpath}\begin{pgfonlayer}{foreground}
\draw[] let \p1=($(\tikzlastnode.north east)+(0,-0.5\pgflinewidth)$),
\p2=($(\tikzlastnode.north west)+(0,-0.5\pgflinewidth)$),
\p3=($(\tikzlastnode.south west)+(0,0.5\pgflinewidth)$),
\p4=($(\tikzlastnode.south east)+(0,0.5\pgflinewidth)$) in
(\p1) -- (\p2) (\p3) -- (\p4);
\end{pgfonlayer}\end{pgfinterruptpath}
}
}},
r/.style={line width=0, fill=orange!50, rounded rectangle, rounded rectangle left arc=0, append after command={% <= for the border
\pgfextra{%
\begin{pgfinterruptpath}
\draw[] let \p1=($(\tikzlastnode.north east)+(0,0.5\pgflinewidth)$),
\p2=($(\tikzlastnode.north west)+(0,0.5\pgflinewidth)$),
\p3=($(\tikzlastnode.south west)+(0,-0.5\pgflinewidth)$),
\p4=($(\tikzlastnode.south east)+(0,-0.5\pgflinewidth)$),
\n1={0.5*(\y1-\y4)} in
(\p3) -- (\p4) arc(-90:90:\n1) -- (\p2);
\end{pgfinterruptpath}
}
}}
]
\node[point] (p1) {};
\node [l, connect] (l) {L};
{[node distance=-0.5\pgflinewidth]
\node [c] (c) {C};}
{[node distance=0]
\node [r] (r) {R};}
\node[point, connect] (p2) {};
\node[font=\tiny, cyan, below=of l] (lbl l-se) {l.se};
\draw[red,->] (lbl l-se) -- (l.south east);
\begin{pgfonlayer}{foreforeground}%apparently, using layer 'foreground' in 'append after command' brings the entire node to the front, which we don't want!
\node[font=\tiny, green, below=of c, yshift=2mm] (lbl c-ne) {c.ne};
\draw[red,->] (lbl c-ne) -- (c.north east);
\end{pgfonlayer}
\node[font=\tiny, orange, below=of r] (lbl r-sw) {r.sw};
\draw[red,->] (lbl r-sw) -- (r.south west);
\end{tikzpicture}
\end{document}
如何确保我的自定义边框在\node
边框内,并绘制在上面的\node
填充颜色?
我曾尝试使用\begin{pgfonlayer}{foreground}
将边框带到前台,但这样做似乎append after command
只是将整个边框\node
带到前台,而边框仍然位于填充物后面。
答案1
您可以通过以下方式减少/增加它们0.5\pgflinewidth
:
\documentclass[border=10pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{calc,chains,scopes,shapes.misc,calc}
\begin{document}
\begin{tikzpicture}[start chain,
node distance=5mm,
every node/.style={on chain},
connect/.style={join=by ->},
point/.style={coordinate},
l/.style={fill=cyan!50, rounded rectangle, rounded rectangle right arc=0, append after command={% <= for the border
\pgfextra{%
\begin{pgfinterruptpath}
\draw[] let \p1=(\tikzlastnode.north west), \p2=(\tikzlastnode.south east), \n1={0.5*(\y1-\y2)} in
($(\tikzlastnode.north east)+(-0.5\pgflinewidth,0)$) -- (\tikzlastnode.north west) arc(90:270:\n1) -- ($(\tikzlastnode.south east)+(-0.5\pgflinewidth,0)$);
\end{pgfinterruptpath}
}
}},
c/.style={fill=green!50, append after command={% <= for the border
\pgfextra{%
\begin{pgfinterruptpath}
\draw[] ($(\tikzlastnode.north east)+(-0.5\pgflinewidth,0)$) -- ($(\tikzlastnode.north west)+(0.5\pgflinewidth,0)$) ($(\tikzlastnode.south west)+(0.5\pgflinewidth,0)$) -- ($(\tikzlastnode.south east)+(-0.5\pgflinewidth,0)$);
\end{pgfinterruptpath}
}
}},
r/.style={fill=orange!50, rounded rectangle, rounded rectangle left arc=0, append after command={% <= for the border
\pgfextra{%
\begin{pgfinterruptpath}
\draw[] let \p1=(\tikzlastnode.north west), \p2=(\tikzlastnode.south east), \n1={0.5*(\y1-\y2)} in
($(\tikzlastnode.north west)+(0.5\pgflinewidth,0)$) -- (\tikzlastnode.north east) arc(90:-90:\n1) -- ($(\tikzlastnode.south west)+(0.5\pgflinewidth,0)$);
\end{pgfinterruptpath}
}
}},
cozy/.style={node distance=-\pgflinewidth}]
\node[point] (p1) {};
\node [l, connect] (l) {L};
% introduced space here on purpose, to demonstrate too long borders
\node [c] (c) {C};
{%[cozy]
\node [r] (r) {R};
}
\node[point, connect] (p2) {};
\end{tikzpicture}
\end{document}
对修订后的 OP 的回应:
也许我没有正确理解您的要求,但这是您想要的吗?
\documentclass[border=10pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{calc,chains,scopes,shapes.misc,backgrounds}
\pgfdeclarelayer{background}
\pgfdeclarelayer{foreground}
%\pgfdeclarelayer{foreforeground}
\pgfsetlayers{background,main,foreground}%,foreforeground}
\begin{document}
\begin{tikzpicture}[start chain,
node distance=5mm,
every node/.style={on chain},
connect/.style={join=by ->},
point/.style={coordinate},
l/.style={line width=\pgflinewidth, fill=cyan!50, rounded rectangle, rounded rectangle right arc=0, append after command={% <= for the border
\pgfextra{\begin{pgfinterruptpath}\begin{pgfonlayer}{foreground}
\draw[] let \p1=($(\tikzlastnode.north east)+(-0.5\pgflinewidth,-\pgflinewidth)$),
\p2=($(\tikzlastnode.north west)+(0,-\pgflinewidth)$),
\p3=($(\tikzlastnode.south west)+(0,\pgflinewidth)$),
\p4=($(\tikzlastnode.south east)+(-0.5\pgflinewidth,\pgflinewidth)$),
\n1={0.5*(\y2-\y3)} in
(\p1) -- (\p2) arc(90:270:\n1) -- (\p4);
\end{pgfonlayer}\end{pgfinterruptpath}}
}},
c/.style={line width=0, fill=green!50, append after command={% <= for the border
\pgfextra{%
\begin{pgfinterruptpath}\begin{pgfonlayer}{foreground}
\draw[] let \p1=($(\tikzlastnode.north east)+(-0.5\pgflinewidth,-0.5\pgflinewidth)$),
\p2=($(\tikzlastnode.north west)+(0.5\pgflinewidth,-0.5\pgflinewidth)$),
\p3=($(\tikzlastnode.south west)+(0.5\pgflinewidth,0.5\pgflinewidth)$),
\p4=($(\tikzlastnode.south east)+(-0.5\pgflinewidth,0.5\pgflinewidth)$) in
(\p1) -- (\p2) (\p3) -- (\p4);
\end{pgfonlayer}\end{pgfinterruptpath}
}
}},
r/.style={line width=0, fill=orange!50, rounded rectangle, rounded rectangle left arc=0, append after command={% <= for the border
\pgfextra{%
\begin{pgfinterruptpath}
\begin{pgfonlayer}{foreground}
\draw[] let \p1=($(\tikzlastnode.north east)+(0,-0.5\pgflinewidth)$),
\p2=($(\tikzlastnode.north west)+(0,-0.5\pgflinewidth)$),
\p3=($(\tikzlastnode.south west)+(0,0.5\pgflinewidth)$),
\p4=($(\tikzlastnode.south east)+(0,0.5\pgflinewidth)$),
\n1={0.5*(\y1-\y4)} in
(\p3) -- (\p4) arc(-90:90:\n1) -- (\p2);
\end{pgfonlayer}
\end{pgfinterruptpath}
}
}}
]
\node[point] (p1) {};
\node [l, connect] (l) {L};
{[node distance=-0.5\pgflinewidth]
\node [c] (c) {C};}
{[node distance=0]
\node [r] (r) {R};}
\node[point, connect] (p2) {};
%\node[font=\tiny, cyan, below=of l] (lbl l-se) {l.se};
%\draw[red,->] (lbl l-se) -- (l.south east);
%
%\begin{pgfonlayer}{foreforeground}%apparently, using layer 'foreground' in 'append after command' brings the entire node to the front, which we don't want!
%\node[font=\tiny, green, below=of c, yshift=2mm] (lbl c-ne) {c.ne};
%\draw[red,->] (lbl c-ne) -- (c.north east);
%\end{pgfonlayer}
%\node[font=\tiny, orange, below=of r] (lbl r-sw) {r.sw};
%\draw[red,->] (lbl r-sw) -- (r.south west);
\end{tikzpicture}
\end{document}
更改c/.style
为
c/.style={line width=0, fill=green!50, append after command={% <= for the border
\pgfextra{%
\begin{pgfinterruptpath}\begin{pgfonlayer}{foreground}
\draw[] let \p1=($(\tikzlastnode.north east)+(-0\pgflinewidth,-0.5\pgflinewidth)$),
\p2=($(\tikzlastnode.north west)+(0\pgflinewidth,-0.5\pgflinewidth)$),
\p3=($(\tikzlastnode.south west)+(0\pgflinewidth,0.5\pgflinewidth)$),
\p4=($(\tikzlastnode.south east)+(-0\pgflinewidth,0.5\pgflinewidth)$) in
(\p1) -- (\p2) (\p3) -- (\p4);
\end{pgfonlayer}\end{pgfinterruptpath}
}
}},
给出
但您需要 TikZ 3 才能实现此目的。TikZ 2 将在填充颜色后面绘制边框。
答案2
一种可能性是使用shapes.multipart
库中的多部分矩形:
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{shapes.multipart}
\tikzset{
mynode/.style={
rectangle split,
rectangle split parts=3,
rectangle split horizontal,
draw,
rounded corners=6pt,
rectangle split part fill={cyan!50, green!50,orange!50},
rectangle split draw splits=false
}
}
\begin{document}
\begin{tikzpicture}
\node[mynode] at (2,3) {L\nodepart{two}C\nodepart{three}R};
\end{tikzpicture}
\end{document}