考虑以下 MWE:
\documentclass[border=1cm]{standalone}
\usepackage{tikz}
\tikzset{
first/.style = {
draw,
ultra thick,
red,
},
second/.style = {
draw,
ultra thin,
blue,
>=latex,
->
}
}
\makeatletter
\pgfdeclareshape{symbol}{
\savedanchor{\southwest}{\pgfpoint{-0.5cm}{-0.5cm}}
\savedanchor{\northeast}{\pgfpoint{0.5cm}{0.5cm}}
\inheritanchorborder[from=rectangle]
\anchor{north}{\pgfpoint{0}{0.25cm}}
\inheritanchor[from=rectangle]{east}
\anchor{south}{\pgfpoint{0}{-0.25cm}}
\inheritanchor[from=rectangle]{west}
\inheritanchor[from=rectangle]{center}
\anchor{inner east}{\pgfpoint{0.5cm - 0.4pt}{0}}
\anchor{text}{\pgfpoint{-.5\wd\pgfnodeparttextbox}{-.5\ht\pgfnodeparttextbox+.5\dp\pgfnodeparttextbox}}
\backgroundpath{
\pgfkeys{/tikz/.cd, first}
\pgfpathmoveto{\pgfpoint{-0.5cm + \pgfkeysvalueof{/pgf/outer xsep} }{0.5cm - (0.5 + sqrt(1.25))*\pgfkeysvalueof{/pgf/outer ysep} }}
\pgfpathlineto{\pgfpoint{0.5cm - sqrt(5)*\pgfkeysvalueof{/pgf/outer xsep} }{0}}
\pgfpathlineto{\pgfpoint{-0.5cm + \pgfkeysvalueof{/pgf/outer xsep} }{-0.5cm + (0.5 + sqrt(1.25))*\pgfkeysvalueof{/pgf/outer ysep} }}
\pgfpathclose
\pgfkeys{/tikz/.cd, second}
\pgfpathmoveto{\pgfpoint{-0.25cm}{-0.5cm}}
\pgfpathlineto{\pgfpoint{0.25cm}{0.5cm}}
}
}
\makeatother
\begin{document}
\begin{tikzpicture}
\node (a) at (0,0) [symbol] {};
\end{tikzpicture}
\end{document}
这是使用上述代码生成的结果:
我希望能够使用我的两个单独的 TikZ 样式分别配置三角形和线条的外观。因此,我实际上希望三角形超粗且为红色,而单条直线应超细、蓝色且配有箭头。
为什么不是这样,我该怎么改?我已经试过了,\pgfusepath{stroke}
没有效果。
答案1
TikZ 使用 PGF 进行所有绘制,这并不奇怪。然而,形状的主要两条路径,\backgroundpath
(背景,因为它将被绘制在文本后面)及其\foregroundpath
(在文本前面),应该由用户“使用”\pgfnode
(每一个\pgfnode
都是\pgfmultipartnode
只有一个节点部分):
\pgfnode{<shape>}{<anchor>}{<Text>}{<name of node>}{<do something with me>}
这<do something with me>
部分与正常路径上发生的事情相同,通常至少
\pgfusepath{stroke}
绘制形状的路径。
现在,当 TikZ 构建路径(\path
和之间的所有内容;
)时,除了围绕“笔”(--
,,.. controls …
...)移动和变换之外,它不会做太多事情,因为像draw
和这样的键fill
只是将它们的操作存储在另一个内部宏中。
只有;
达到时,真正的魔法才会真正发生。存储的选项和设置会被执行,内容会被整理(剪辑?填充?绘制?阴影?淡入淡出?路径图片?双重?前置和后置操作?),错误消息会被调用等等。
因此,当 TikZ 找到时,;
它将执行\tikz@finish
。
并且当 TikZ 添加节点时也将使用此宏,因为节点的路径应该与 PGF/TikZ 中的任何其他路径相同:
\pgfmultipartnode{<shape>}{<anchor>}{<name of node>}{%
\pgfutil@tempdima=\pgflinewidth%
{\begingroup\tikz@finish}%
\global\pgflinewidth=\pgfutil@tempdima%
}%
它对线宽进行了一些调整,我假设它恢复了路径的线宽,因为\tikz@finish
可能全局将其设置为其他值。
因为\tikz@finish
(记住,;
)还会关闭启动的组\path
,所以需要一个\begingroup
。 (这些设置是预先设置的,但在这个实际上不执行任何操作的组内仍然有效。)
长话短说,你需要指示你的形状使用 er \tikz@finish
。
这可能只是
\backgroundpath{%
\begingroup
\tikzset{first}%
\pgfpathmoveto
{\pgfpoint{-0.5cm + \pgfkeysvalueof{/pgf/outer xsep}}
{ 0.5cm - (0.5 + sqrt(1.25))*\pgfkeysvalueof{/pgf/outer ysep}}}%
\pgfpathlineto
{\pgfpoint{0.5cm - sqrt(5)*\pgfkeysvalueof{/pgf/outer xsep}}{0pt}}%
\pgfpathlineto
{\pgfpoint{-0.5cm + \pgfkeysvalueof{/pgf/outer xsep}}
{-0.5cm + (0.5 + sqrt(1.25))*\pgfkeysvalueof{/pgf/outer ysep}}}%
\pgfpathclose
\tikz@finish
\begingroup
\tikzset{second}%
\pgfpathmoveto{\pgfqpoint{-0.25cm}{-0.5cm}}%
\pgfpathlineto{\pgfqpoint{0.25cm}{0.5cm}}%
\tikz@finish
}
不需要\begingroup\tikzset{first}
位于路径的开头,除非您想使用变换和其他花哨的东西来实际改变路径。但由于您只使用draw
、线宽和颜色,因此也可以这样做:
\pgfpathmoveto{\pgfqpoint{-0.25cm}{-0.5cm}}%
\pgfpathlineto{\pgfqpoint{0.25cm}{0.5cm}}%
\begingroup
\tikzset{second}%
\tikz@finish
(转型实际上需要\let\tikz@transform\relax
努力,但那是另一回事。)
因此我们实际上有三条路径:first
、second
和 TikZ 通过调用 完成的空路径\pgfmultinodepart
。
最好将这些内容移到其他路径中,这样形状就可以明确地执行某些操作(描边、填充等),而不是使用用户应该“使用”的路径之一。但这一切都取决于您的实际用例 - 以及您的用户是谁。
也就是说,pic
可能是更好的选择,但这也取决于用例。
代码
\documentclass[border=1mm, tikz]{standalone}
\tikzset{
first/.style = {draw, ultra thick, red},
second/.style = {draw, ultra thin, blue, >=latex, ->}}
\makeatletter
\pgfdeclareshape{symbol}{
\savedanchor{\southwest}{\pgfqpoint{-0.5cm}{-0.5cm}}
\savedanchor{\northeast}{\pgfqpoint{0.5cm}{0.5cm}}
\inheritanchorborder[from=rectangle]
\anchor{north}{\pgfqpoint{0pt}{0.25cm}}
\inheritanchor[from=rectangle]{east}
\anchor{south}{\pgfqpoint{pt0}{-0.25cm}}
\inheritanchor[from=rectangle]{west}
\inheritanchor[from=rectangle]{center}
\anchor{inner east}{\pgfpoint{0.5cm - 0.4pt}{+0pt}}
\anchor{text}{\pgfpoint{-.5\wd\pgfnodeparttextbox}{-.5\ht\pgfnodeparttextbox+.5\dp\pgfnodeparttextbox}}
\backgroundpath{%
\begingroup
% \let\tikz@transform\relax if you want transformations to work
\tikzset{first}%
\pgfpathmoveto
{\pgfpoint{-0.5cm + \pgfkeysvalueof{/pgf/outer xsep}}
{ 0.5cm - (0.5 + sqrt(1.25))*\pgfkeysvalueof{/pgf/outer ysep}}}%
\pgfpathlineto
{\pgfpoint{0.5cm - sqrt(5)*\pgfkeysvalueof{/pgf/outer xsep}}{0pt}}%
\pgfpathlineto
{\pgfpoint{-0.5cm + \pgfkeysvalueof{/pgf/outer xsep}}
{-0.5cm + (0.5 + sqrt(1.25))*\pgfkeysvalueof{/pgf/outer ysep}}}%
\pgfpathclose
\tikz@finish
\begingroup
\tikzset{second}%
\pgfpathmoveto{\pgfqpoint{-0.25cm}{-0.5cm}}%
\pgfpathlineto{\pgfqpoint{0.25cm}{0.5cm}}%
\tikz@finish
}
}
\makeatother
\begin{document}
\begin{tikzpicture}
\matrix[nodes=symbol] {
\node {}; & \node [green] {.}; \\
\node[dashed] {}; & \node[second/.append style={green}]{.}; \\
};
\end{tikzpicture}
\end{document}