我想使用图片轻松快速地创建新的节点形状。遗憾的是,我找不到如何使用内部节点来定义锚点。例如,我希望 B 指向地面符号中的小 x:
梅威瑟:
\documentclass{article}
\usepackage{amsmath}
\usepackage{tikz-cd}
\begin{document}
\tikzset{
groundpic/.pic={
% Code for the ground
\draw[line width=.4pt]
(0,0) -- (1mm,0)
-- +(0,1mm) -- +(0,-1mm)
++(.4mm,0)
-- +(0,.7mm) -- +(0,-.7mm) node[anchor=center,scale=.5,name=myanchor] {x}
++(.4mm,0)
-- +(0,.35mm) -- +(0,-.35mm)
;
},
ground/.style={
shape=coordinate, % Otherwise the arrow will not point to the center
append after command={
pic[scale=2] {groundpic}
},
},
}
Goal: add an arrow to x, but end anchor=myanchor fails:
\noindent\begin{tikzcd}
A \rar & |[ground]| & \\
B \ar[
ru,
% end anchor=myanchor
]
\end{tikzcd}
\end{document}
答案1
节点不能是真正的锚点。锚点始终是一个单点。它不能是另一个节点。
不过,有两件事可以做:
我们可以向现有节点(或坐标,只是一个特殊节点)添加一个锚点。
为此,我进行了调整我的答案到 ”路径图片添加自定义锚点”这有问题,但链接的答案中没有显示。现在应该更强大了。
我们可以命名图片中的一个节点,该节点实际上是
<pic name><node name>
在全局范围内命名的。(TikZ 设置了,name prefix = <pic name>
这意味着每个命名的坐标或节点都使用此前缀,除非name prefix ..
给出。)如果我们也将节点命名为(数学)节点矩阵命名其单元的节点,我们可以轻松地将其合并到 TikZ-CD 中(参见对样式的调整
ground
)。
现在我们实际上可以使用
\ar[ru, name suffix=<node name>]
但这适用于起点和目标以及我们在途中定义的每个坐标/节点。
对于这个小例子,它仅适用于开始而不是目标?
\begin{tikzcd}[arrows=help lines]
|[ground]| \ar[r, bend right=90, name suffix=-east]
& |[ground]| \ar[l, bend right=90, name suffix=-east]
\end{tikzcd}
奇怪。(当 TikZ 遇到节点坐标规范时,即(<node name>)
它首先尝试查找具有名称前缀和后缀的节点,如果找不到,它会检查未添加这些的节点。)
这就是我提出密钥from pic node
和的原因to pic node
(这也-
为您添加了):
\begin{tikzcd}[arrows=help lines]
|[ground]| \ar[r, bend right=90, from pic node=east, to pic node=east]
& |[ground]| \ar[l, bend right=90, from pic node=east, to pic node=east]
\end{tikzcd}
这些键应该在指定目标后使用,即在ru
使用to
/之后from
,否则设置将再次丢失。
代码
\documentclass[tikz]{standalone}
%\documentclass{article}
\usepackage{amsmath}
\usepackage{tikz-cd}
\makeatletter
\tikzset{
add anchor to node/.code n args={3}{%
\edef\tikz@temp##1{% \tikz@pp@name/\tikzlastnode needs to be expanded
\noexpand\pgfutil@g@addto@macro\expandafter\noexpand\csname
pgf@sh@ma@\tikz@pp@name{#1}\endcsname{%
\def\expandafter\noexpand\csname pgf@anchor@\csname
pgf@sh@ns@\tikz@pp@name{#1}\endcsname @#2\endcsname{##1}%
}%
}%
\tikz@temp{#3}%
},
add anchor to pic'/.style={/tikz/add anchor to pic={#1}{-#1}},
add anchor to pic/.code 2 args={%
% If base coordinate isn't created yet, do so at (0,0)
% in the current coordinate system!
\pgfutil@ifundefined{pgf@sh@ns@\tikz@pp@name{}}{%
\pgfcoordinate{\tikz@pp@name{}}{\pgfpointorigin}%
}{}%
\begingroup
% What is the distance between coordinate and base?
% We have to do this in the coordinate system of the base coordinate.
\pgfsettransform{\csname pgf@sh@nt@\tikz@pp@name{}\endcsname}%
\pgf@process{\pgfpointanchor{\tikz@pp@name{#2}}{center}}%
% This distance is the new anchors coordinate
% in the base's coordinate system.
% Adding an anchor to a node must be global
% which is why we can do this inside the group.
\pgfkeysalso{
/tikz/add anchor to node/.expanded=%
{}{#1}{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}
}%
\endgroup
}%
}
\tikzcdset{
from pic node/.code=\edef\tikzcd@ar@start{\tikzcd@ar@start-#1},
to pic node/.code=\edef\tikzcd@ar@target{\tikzcd@ar@target-#1}}
\makeatother
\tikzset{
groundpic/.pic={
% Code for the ground
\draw[line width=.4pt] (0,0) -- (1mm,0)
+(0, 1mm) coordinate(-t1) -- +(0,-1mm) coordinate(-b1)
++(.4mm,0) +(0,.7mm) coordinate(-t2) -- +(0,-.7mm) coordinate(-b2)
++(.4mm,0) +(0,.35mm) coordinate(-t3)-- +(0,-.35mm)coordinate(-b3)
node[scale=.4, below, rotate=90, midway, inner sep=+3pt, rectangle]
(-east) {Ground};
% \node[draw, help lines](){4444};
% \coordinate(-b4) at (.west);
\tikzset{add anchor to pic'/.list={t1, b1, t2, b2, t3, b3}}
},
ground/.style={
shape=coordinate, yshift=axis_height,
append after command={
pic[scale=2,at=(\tikzlastnode),name=\tikzlastnode]{groundpic}
}
}
}
\begin{document}
\begin{tikzcd}
A \rar & |[ground]| \\
B
\foreach \num in {1,2,3}{
\foreach\tORb/\leftORright in {t/left,b/right}{
\expanded{\noexpand\ar[
bend \leftORright, -, help lines, ru , end anchor=\tORb\num]}
}
}
\ar[ru, out=0, in=-30, "Here's the ground"' math mode=false, name suffix=-east]
\end{tikzcd}
\begin{tikzcd}[arrows=help lines]
|[ground]| \ar[r, bend right=90, name suffix=-east]
& |[ground]| \ar[l, bend right=90, name suffix=-east]
\end{tikzcd}
\begin{tikzcd}[arrows=help lines]
|[ground]| \ar[r, bend right=90, from pic node=east, to pic node=east]
& |[ground]| \ar[l, bend right=90, from pic node=east, to pic node=east]
\end{tikzcd}
\end{document}
输出
答案2
我认为您的问题来自于这样一个事实:end anchor
仅将图中相应元素(即箭头指向的元素)定义的坐标作为参数。
图中黑色箭头起始于乙使用end anchor=240
,即它结束于右上元素边界上的点,该点由相对于牛轴。红色箭头为正常箭头。
评论我稍微重新定义了你的pic
对象;我认为,如果你想在图表中使用它,最好使用相对长度单位来定义它。
代码
\documentclass[11pt, margin=5mm]{standalone}
\usepackage{amsmath}
\usepackage{tikz-cd}
\begin{document}
\tikzset{
pics/ground pic/.style={%
code={%
\draw
(0, 0) -- +(0, 1.5ex) -- +(0,-1.5ex)
++(.5ex, 0) -- +(0, 1ex) -- +(0, -1ex)
node[anchor=center, scale=.5, outer sep=2ex] (-g) {x}
++(.5ex, 0) -- +(0, .65ex) -- +(0, -.65ex);
\draw (0, 0) -- (-1ex, 0);
}
},
ground/.style={%
outer xsep=.3ex, outer ysep=1ex,
insert path={%
pic[yshift=.5ex] {ground pic}
}
}
}
\begin{tikzcd}
A \arrow[r] & |[ground]|\phantom{A} \\
B \arrow[ru, end anchor=240]
\arrow[ru, red]
\end{tikzcd}
\end{document}
答案3
我不确定tikz-cd
这样做是否正确,但也许你心里有特别的想法。
正如评论中已经提出的,您可以命名 pic 中的坐标和节点,然后通过将这些名称附加到 pic 的名称来引用它们。因此,例如,如果您用小 x-myanchor
和 pic命名节点mypic
,那么您可以使用 引用此 pic 中带有小 x 的节点mypic-myanchor
。由于它是一个节点,您还可以引用其锚点,例如使用mypic-myanchor.south
。
现在,下一个问题是如何告诉 Ti钾\arrow
Z 绘制指向某个坐标的箭头,该坐标不是在环境中使用(或\ar
)宏时通常指向的坐标tikzcd
。这可以通过以某种方式设计此箭头来实现,以便将目标路径替换为以相关坐标(或锚点)为目标的另一条路径。
可能的解决方案如下:
\documentclass{standalone}
\usepackage{tikz-cd}
\tikzset{
groundpic/.pic={
% Code for the ground
\draw[line width=.4pt]
(0,0) -- (1mm,0)
-- +(0,1mm) -- +(0,-1mm)
++(.4mm,0)
-- +(0,.7mm) -- +(0,-.7mm) node[anchor=center,scale=.5] (-myanchor) {x}
++(.4mm,0)
-- +(0,.35mm) -- +(0,-.35mm)
;
},
ground/.style={
shape=coordinate, % Otherwise the arrow will not point to the center
append after command={
pic[scale=2] (#1) {groundpic}
},
},
custom target/.style={
to path={
-- (#1)
}
}
}
\begin{document}
\begin{tikzcd}
A \rar & |[ground=mypic]| & \\
B \ar[
ru,
custom target=mypic-myanchor.south
]
\end{tikzcd}
\end{document}
感谢 Qrrbrbirlbel,我了解到tikz-cd
已经提供了一个选项to
,可以完全按照我使用自己的custom target
选项尝试的方式执行操作。因此,您也可以执行以下操作:
\documentclass{standalone}
\usepackage{tikz-cd}
\tikzset{
groundpic/.pic={
% Code for the ground
\draw[line width=.4pt]
(0,0) -- (1mm,0)
-- +(0,1mm) -- +(0,-1mm)
++(.4mm,0)
-- +(0,.7mm) -- +(0,-.7mm) node[anchor=center, scale=.5] (-myanchor) {x}
++(.4mm,0)
-- +(0,.35mm) -- +(0,-.35mm)
;
},
ground/.style={
shape=coordinate, % Otherwise the arrow will not point to the center
append after command={
pic[scale=2] (#1) {groundpic}
},
}
}
\begin{document}
\begin{tikzcd}
A \rar & |[ground=mypic]| & \\
B \ar[
ru,
to=mypic-myanchor.south
]
\end{tikzcd}
\end{document}