我正在尝试制作一些自己的 PGF 形状,以便稍后在 TikZ 中使用它。该形状应为正方形,内部没有文本,并且应使用指定的边框样式。考虑以下 MWE:
\documentclass[border=1mm]{standalone}
\usepackage{tikz}
\makeatletter
\newlength\mylength
\tikzset{
length/.code={\setlength{\mylength}{#1}},
length = 8mm,
border style/.store in=\borderstyle,
border style = thick,
}
\pgfdeclareshape{myshape}{
\inheritsavedanchors[from=rectangle]
\inheritanchorborder[from=rectangle]
\inheritanchor[from=rectangle]{center}
\inheritanchor[from=rectangle]{north}
\inheritanchor[from=rectangle]{south}
\inheritanchor[from=rectangle]{west}
\inheritanchor[from=rectangle]{east}
% define additional drawing commands
\backgroundpath{
% coordinates on frame
\pgf@xa=-0.5\mylength \pgf@ya=-0.5\mylength
\pgf@xb=0.5\mylength \pgf@yb=0.5\mylength
% where can I specify that this path needs to use the \borderstyle?
\pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}}
\pgfpathlineto{\pgfpoint{\pgf@xa}{\pgf@yb}}
\pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@yb}}
\pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@ya}}
\pgfpathclose
}
}
\makeatother
\begin{document}
\begin{tikzpicture}
\node[draw,shape=myshape, label=above:label] at (0,0) (some node) {};
\draw[<-] (some node) -- ++(0,-1);
\end{tikzpicture}
\end{document}
它确实创建了一个边长为 的正方形length
,这正是我想要的。但south
锚点似乎并不在正方形的南边,而是在正方形内部的某个地方。我猜这是因为我在形状内没有文本。我怎样才能移动所有锚点,使它们位于正方形上?此外,我怎样才能让正方形使用border style
上面定义的 I?标签位置也是错误的。它应该在正方形外面,因为我不想在里面放任何文本。
答案1
这是不声明新形状的替代方案。我使用 添加了一个附加元素path picture
。由于我不知道您要添加什么,我只选择了对角线,但显然您可以添加任何您想要的。(我个人不会将样式存储在宏中,但会使用.../.style=...
它,但我将您的建议保留在这里。)
\documentclass[border=1mm]{standalone}
\usepackage{tikz}
\newlength\mylength
\tikzset{
length/.code={\setlength{\mylength}{#1}},
length = 8mm,
border style/.store in=\borderstyle,
border style = thick,
}
\tikzset{myshape/.style={draw,\borderstyle,
minimum size=\mylength,
path picture={
\draw (path picture bounding box.south west) --
(path picture bounding box.north east);
}}}
\begin{document}
\begin{tikzpicture}
\node[myshape, label=above:label] at (0,0) (some node){};
\draw[<-] (some node) -- ++(0,-1);
\end{tikzpicture}
\end{document}
答案2
这就是你想要的吗?
\documentclass[border=1mm]{standalone}
\usepackage{tikz}
\makeatletter
\newlength\mylength
\tikzset{
length/.code={\setlength{\mylength}{#1}},
length = 8mm,
border style/.store in=\borderstyle,
border style = thick,
}
\pgfdeclareshape{myshape}{
\savedanchor{\southwest}{\pgfpoint{-0.5\mylength}{-0.5\mylength}}
\savedanchor{\northeast}{\pgfpoint{0.5\mylength}{0.5\mylength}}
\inheritanchorborder[from=rectangle]
\inheritanchor[from=rectangle]{center}
\inheritanchor[from=rectangle]{north}
\inheritanchor[from=rectangle]{south}
\inheritanchor[from=rectangle]{west}
\inheritanchor[from=rectangle]{east}
\anchor{text} % this is used to center the text in the node
{\pgfpoint{-.5\wd\pgfnodeparttextbox}{-.5\ht\pgfnodeparttextbox}}
% define additional drawing commands
\backgroundpath{
\pgfkeys{/tikz/.cd,
\borderstyle}
\pgfsetlinewidth{\pgflinewidth}
% coordinates on frame
\pgf@xa=-0.5\mylength \pgf@ya=-0.5\mylength
\pgf@xb=0.5\mylength \pgf@yb=0.5\mylength
% where can I specify that this path needs to use the \borderstyle?
\pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}}
\pgfpathlineto{\pgfpoint{\pgf@xa}{\pgf@yb}}
\pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@yb}}
\pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@ya}}
\pgfpathclose
}
}
\makeatother
\begin{document}
\begin{tikzpicture}
\node[draw,shape=myshape, label=above:label] at (0,0) (some node) {};
\draw[<-] (some node) -- ++(0,-1);
\end{tikzpicture}
\end{document}
答案3
好的,我已经很接近了。我得到了以下信息,感谢约翰·科米洛:
\documentclass[border=1cm]{standalone}
\usepackage{tikz}
\usetikzlibrary{shapes}
\begin{document}
\tikzset{
shape example/.style={
color=black!30,
draw,
fill=yellow!30,
line width=.5cm,
inner xsep=2.5cm,
inner ysep=0.5cm}
}
\makeatletter
\pgfdeclareshape{myrect}{
\savedanchor{\southwest}{\pgfpoint{-6cm-0.5\pgflinewidth}{-6cm-0.5\pgflinewidth}}
\savedanchor{\northeast}{\pgfpoint{6cm+0.5\pgflinewidth}{6cm + 0.5\pgflinewidth}}
\inheritanchorborder[from=rectangle]
\inheritanchor[from=rectangle]{north}
\inheritanchor[from=rectangle]{east}
\inheritanchor[from=rectangle]{south}
\inheritanchor[from=rectangle]{west}
\inheritanchor[from=rectangle]{center}
\anchor{text} % this is used to center the text in the node
{\pgfpoint{-.5\wd\pgfnodeparttextbox}{-.5\ht\pgfnodeparttextbox}}
\backgroundpath{
% Rectangle box
\pgfpathrectanglecorners{\pgfpointadd{\southwest}{\pgfpoint{0.5\pgflinewidth}{0.5\pgflinewidth}}}{\pgfpointadd{\northeast}{\pgfpoint{-0.5\pgflinewidth}{-0.5\pgflinewidth}}}
\pgfusepath{draw, fill}
}
}
\pgfdeclareshape{mytri}{
\savedanchor{\southwest}{\pgfpoint{-6cm-0.5\pgflinewidth}{-6cm-0.5\pgflinewidth}}
\savedanchor{\northeast}{\pgfpoint{6cm+0.5\pgflinewidth}{6cm + 0.5\pgflinewidth}}
\inheritanchorborder[from=rectangle]
\inheritanchor[from=rectangle]{north}
\inheritanchor[from=rectangle]{east}
\inheritanchor[from=rectangle]{south}
\inheritanchor[from=rectangle]{west}
\inheritanchor[from=rectangle]{center}
\anchor{text} % this is used to center the text in the node
{\pgfpoint{-.5\wd\pgfnodeparttextbox}{-.5\ht\pgfnodeparttextbox}}
\backgroundpath{
% Rectangle box
\pgfpathmoveto{\pgfpoint{-6cm}{6cm}}
\pgfpathlineto{\pgfpoint{6cm}{0}}
\pgfpathlineto{\pgfpoint{-6cm}{-6cm}}
\pgfpathclose
\pgfusepath{draw, fill}
}
}
\makeatother
\Huge
\begin{tikzpicture}
\node at (0,0) [name=s,myrect, minimum width=12cm, minimum height=12cm, inner sep = 0pt, shape example, label=above:label] {};
\node at (30,0) [name=s2,mytri, minimum width=12cm, minimum height=12cm, inner sep = 0pt, shape example, label=above:label] {};
\draw (-6cm,-6cm) -- (6cm,-6cm);
\foreach \x/\p in {north/above, east/right, south/below, west/left}
\draw[shift=(s.\x)] plot[mark=x] coordinates{(0,0)} node[\p] {\color{red}\scriptsize\texttt{(s.\x)}};
\draw[thin, red] (s2.west) |- (s2.north) -| (s2.east) |- (s2.south) -| cycle;
\draw[thin, red] (s.west) |- (s.north) -| (s.east) |- (s.south) -| cycle;
\foreach \x/\p in {north/above, east/right, south/below, west/left}
\draw[shift=(s2.\x)] plot[mark=x] coordinates{(0,0)} node[\p] {\color{red}\scriptsize\texttt{(s2.\x)}};
\draw[>=latex, ->] (s) -- (s2);
\end{tikzpicture}
\end{document}
对于矩形,锚点现在似乎已正确对齐(即锚点实际上位于线条的外侧,就像 TikZ 中的普通矩形一样),如果使用非常大的线条粗细,这一点就变得很明显。要实现这一点,必须\pgflinewidth
考虑线条端点的坐标。
我想知道是否有一种机制可以自动校正线条粗细?例如,如果考虑三角形,则显然路径点的校正变得更加麻烦,简单地减去是错误的\pgflinewidth
。