我正在尝试创建pic
像节点一样运行的 s。按照转移范围和pic
命名范围,我设法手动创建pic
并移动它们以使其像节点一样运行。
主要问题是,如果的pic
构造方式不是使第一个节点保持在的中心scope
,那么整体pic
就会发生移动(见下面的例子)。
我的问题是如何自动重新居中范围,使得无论范围如何pic
构造,锚点始终位于其中心。有没有办法像使用但一样自动将范围居中pic shift
?
平均能量损失
\documentclass[convert={outext=.png}]{standalone}
\usepackage{tikz}
\usetikzlibrary{positioning}
\begin{document}
\makeatletter
\begin{tikzpicture}[
% https://tex.stackexchange.com/a/185283/7561
pic shift/.store in=\shiftcoord,
pic shift={(0,0)},
% https://tex.stackexchange.com/a/241737/7561
pics/named scope code/.style 2 args={code={\tikz@fig@mustbenamed%
\begin{scope}[shift={\shiftcoord}, local bounding box/.expanded=\tikz@fig@name, #1]#2\end{scope}%
}},
% this pic is shifted since the other nodes are placed at the right of the first one
pics/balls/.style = {named scope code={node distance=5pt}{%
\node[draw, circle] (c1) {};
\node[draw, circle, right=of c1] (c2) {};
\node[draw, circle, right=of c2] (c3) {};
}},
% same as the above pic, but now the nodes are placed around the first one instead
pics/center balls/.style = {named scope code={node distance=5pt}{%
\node[draw, circle] (c1) {};
\node[draw, circle, left=of c1] (c2) {};
\node[draw, circle, right=of c1] (c3) {};
}},
]
% base node for reference
\node (o) {O};
% first pic
\draw pic[right=of o] (b) {balls};
% this is shifted
\draw pic[below=5pt of b] (b2) {balls};
% this is centered by moving it by hand
\draw pic[below=20pt of b, pic shift={(-.5,0)}] (b2) {balls};
% this is centered by design
\draw pic[below=35pt of b] (b3) {center balls};
\end{tikzpicture}
\makeatother
\end{document}
答案1
我猜这是我以前遇到过的一个居中问题:试图将非中心元素pic
放在节点的中心。如果是这样,我的解决方案是先创建一个\savebox
,然后再使用\usebox
。
\documentclass[tikz,border=5mm]{standalone}
\usetikzlibrary{matrix}
\begin{document}
\begin{tikzpicture}
\tikzset{cube/.pic={
\path
(0,0) coordinate (A1)
(1,0) coordinate (A2)
(1,1) coordinate (A3)
(0,1) coordinate (A4);
\foreach \i in {1,...,4}
\path (A\i)+(45:.5) coordinate (B\i);
\draw[pic actions] (A1)--(A2)--(B2)--(B3)--(B4)--(A4)--cycle;
\draw[dashed] (B1)--(A1) (B1)--(B2) (B1)--(B4);
\draw (A3)--(A4) (A3)--(A2) (A3)--(B3);
}}
\newsavebox{\tempbox}
\savebox{\tempbox}{\tikz{\pic[fill=yellow!30]{cube};}}
% later use \usebox{\tempbox} to center the cube
\draw[gray!50] (0,0) grid (6,3);
\path (1,1) pic{cube};
\path (4,1) node{\usebox{\tempbox}};
\fill[red]
(1,1) circle (2pt) (4,1) circle (2pt);
\end{tikzpicture}
\end{document}
\documentclass[tikz,border=5mm]{standalone}
\usetikzlibrary{matrix}
\begin{document}
\begin{tikzpicture}
\tikzset{cube/.pic={
\path
(0,0) coordinate (A1)
(1,0) coordinate (A2)
(1,1) coordinate (A3)
(0,1) coordinate (A4);
\foreach \i in {1,...,4}
\path (A\i)+(45:.5) coordinate (B\i);
\draw[pic actions] (A1)--(A2)--(B2)--(B3)--(B4)--(A4)--cycle;
\draw[dashed] (B1)--(A1) (B1)--(B2) (B1)--(B4);
\draw (A3)--(A4) (A3)--(A2) (A3)--(B3);
}}
\newsavebox{\tempbox}
\savebox{\tempbox}{\tikz{\pic[scale=1.5,fill=yellow!30]{cube};}}
% later use \usebox{\tempbox} to center the cube
\matrix (m) [matrix of nodes,
nodes in empty cells,
row sep=-\pgflinewidth,
column sep=-\pgflinewidth,
nodes={minimum height=10mm,draw=magenta!50,anchor=center},
column 1/.style={nodes={minimum width=8 cm,text width=6cm,align=center}},
column 2/.style={nodes={minimum width=4 cm}},
row 2/.style={nodes={minimum height=3cm}},
]{
Volume&Figure\\
Volume of the cube $V=a^3$&\usebox{\tempbox}\\
};
\end{tikzpicture}
\end{document}
答案2
以下是使用新设施的解决方案tikzmark
用于重新定位图片的库,如固定 TiKZ 图片。在撰写本文时,这尚未在 CTAN 上,因此请tikzmark.dtx
从 github 下载并运行tex tikzmark.dtx
以生成文件。
\documentclass{article}
%\url{https://tex.stackexchange.com/q/612364/86}
\usepackage{tikz}
\usetikzlibrary{
positioning,
tikzmark,
fit
}
\makeatletter
\tikzset{
save pic bounding box/.code={
\tikz@fig@mustbenamed
\tikzset{local bounding box/.expanded=\tikz@fig@name}
}
}
\makeatother
\begin{document}
\begin{tikzpicture}[
balls/.pic={
\begin{scope}[adjust pic position, node distance=5pt, save pic bounding box]
\node[draw, circle] (c1) {};
\node[draw, circle, right=of c1] (c2) {};
\node[draw, circle, right=of c2] (c3) {};
\end{scope}
},
% same as the above pic, but now the nodes are placed around the first one instead
center balls/.pic={
\begin{scope}[adjust pic position, node distance=5pt, save pic bounding box]
\node[draw, circle] (c1) {};
\node[draw, circle, left=of c1] (c2) {};
\node[draw, circle, right=of c1] (c3) {};
\end{scope}
},
]
% base node for reference
\node (o) {O};
% first pic
\draw pic[right=of o] (b) {balls};
\node[fit=(b),draw,inner sep=0pt,node contents={}];
\draw (b.south) -- ++(0,-5pt);
\draw[red] ([xshift=1pt]b.south) -- ++(0,-20pt);
\draw[blue] ([xshift=-1pt]b.south) -- ++(0,-35pt);
% Note that the `below=5pt of b` means that the default anchor in the pic is set to `north`
\draw pic[below=5pt of b] (b2) {balls};
% this is centred using tikzmark
\draw pic[below=20pt of b, pic anchor={(b3.center)}] (b3) {balls};
% this is centred by design
\draw pic[below=35pt of b] (b4) {center balls};
\end{tikzpicture}
\end{document}
仅当能够引用图片之外的位置时才需要该键save pic bounding box
。仅定位图片时不需要该键。
编译代码时我注意到一件奇怪的事情。通过below=5pt of b
在图片上使用键,您实际上将图片内节点的默认锚点设置为north
。为了展示这种效果,我从第一张图片向下绘制了线条,延伸 5pt、20pt 和 35pt。在第二组和第四组圆圈中,它们位于其线条范围以下。在第三组(使用 tikzmark 定位)中,它们位于线条末端的中心。这是因为 tikzmark 定位系统表示“将给定的坐标放置在图片的位置”,因此一旦计算出位置(从),给below=20pt of b
定的坐标就会放在那里。要获得节点可能期望的行为,请使用pic anchor=(b3.north)
。
经过更多的实验,我们可以得到以下关键信息:
auto pic anchor/.style={
pic anchor={(\tikz@fig@name.\tikz@anchor)}
}
应该调用后使用below=5pt of b
(或其他)和而不是pic anchor
键和,然后拾取由键设置的锚点below
并将其应用于pic anchor
定位系统。(需要进行更多测试以确保不会出现和\tikz@fig@name
被\tikz@anchor
覆盖的情况,因为它们是在此时设置的,但pic anchor
直到绘制完图片后才实际使用;我认为范围意味着图片内的任何东西都不会影响它们,但最好确保这一点。)