自动移动 tikz 图片的范围

自动移动 tikz 图片的范围

我正在尝试创建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)

使用 tikzmark 将图片置于中心


经过更多的实验,我们可以得到以下关键信息:

  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直到绘制完图片后才实际使用;我认为范围意味着图片内的任何东西都不会影响它们,但最好确保这一点。)

相关内容