我有一些 Tikz 图形,我将它们用在多个其他图形中。现在我将它们放在一个范围内,并使用 xshift/yshift/scale 将它们放置在我想要的位置。我有一个例子。我需要一个 LaTeX 文档中的图形,其 \linewidth 为 336pt,因此我想以此宽度处理我的图片。我首先创建一个所需宽度和比例的框架。接下来我想在其中放置一些带有一些内容的框。其中一个框包含一个火柴人,我也将其用在其他图形中。我当前的解决方案如下所示:
以下是一个例子:
\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{positioning}
\begin{document}
\begin{tikzpicture}[node distance=0pt]
% Stickman
\begin{scope}[xshift=38pt, yshift=105pt, anchor=sout west, scale=0.45,local bounding box=person]
\draw[thin, line cap=round] (0.05,1) -- (-0.05, 1.1); % hair1
\draw[thin, line cap=round] (-0.05,1) -- (-0.2, 1.12); % hair1
\draw[thick] (0,0) circle [radius=1]; % head
\draw[thin] plot [smooth,tension=1.5] coordinates{(-0.7,0.45) (-0.5,0.52) (-0.4,0.52)}; % leyebrow
\draw[fill=black] (-0.5,0.25) ellipse (0.1 and 0.15);
\draw[thin] plot [smooth,tension=1.5] coordinates{(0.3,0.40) (0.1,0.50) (-0.1,0.50)}; % leyebrow
\draw[fill=black] (0.1,0.20) ellipse (0.1 and 0.15);
\draw[thick] plot [smooth,tension=1.5] coordinates{(-0.75,-0.4) (-0.2,-0.6) (0.3,-0.53)}; % mouth
\draw[thick] (-0.15,-1) .. controls (-0.4,-2.5) .. (-0.5,-4); % torso
\draw[thick] (-0.2,-1.3) -- (0.35, -2.55) -- (1.5, -2.2); % rarm
\draw[thick,rotate around={110:(1.5, -2.2)}] (1.5, -2.4) ellipse (0.1 and 0.2);
\draw[thick] (-0.2,-1.3) -- (-1.55, -2.55) -- (-1.75, -4.1); % rarm
\draw[thick,rotate around={-5:(-1.75, -4.1)}] (-1.75, -4.3) ellipse (0.1 and 0.2);
\draw[thick] (-0.5,-4) -- (0.7, -5.3) -- (1.4,-6.8); % rleg
\draw[thick,rotate around={25:(1.4,-6.8)}] (1.65,-6.8) ellipse (0.25 and 0.1);
\draw[thick] (-0.5,-4) -- (-0.95,-5.8) -- (-2.3,-7); % rleg
\draw[thick,rotate around={-35:(-2.3,-7)}] (-2.05,-7) ellipse (0.25 and 0.1);
\end{scope}
\tikzstyle{box}=[draw, very thick, minimum height=120pt] % box style
% Stickman Box
\node[box, anchor=south west, minimum width=60pt] (FrameInput) at (5pt, 5pt) {};
\node[above=of FrameInput] (xy) {Input};
% Second box
\node[box, minimum width=120pt, right=of FrameInput, xshift=15pt] (FrameNextStep) {};
\node[above=of FrameNextStep] (xy) {NextStep};
% Box Connections
\path[->, very thick] (FrameInput) edge (FrameNextStep);
% Picture Frame
\draw[thick] (0,0) rectangle (336pt, 150pt); % frame
\end{tikzpicture}
\end{document}
我只是想知道是否有更好的方法来解决这个问题。例如,通过指定我的火柴人应该具有等于 FrameInput 框的最大宽度/高度,而无需手动调整范围的比例参数。这同样适用于 x/y 移位,是否有更好/更优雅的方式来定位它?
答案1
- 计算环境中原始火柴人的宽度和高度以及左下角锚点
pgfinterruptboundingbox
。 - 计算移位偏移和比例值
- 画出正确的火柴人,左下角位于
(0, 0)
以下是代码:
\documentclass[border=1cm]{standalone}
\usepackage{tikz}
\usetikzlibrary{positioning, calc}
\makeatletter
\tikzset{
stickman height/.store in=\stickman@height,
stickman height=2cm,
stickman x sep/.store in=\stickman@x@sep,
stickman x sep=3pt,
stickman y sep/.store in=\stickman@y@sep,
stickman y sep=3pt,
}
\gdef\@stickman{
\draw[thin, line cap=round] (0.05,1) -- (-0.05, 1.1); % hair1
\draw[thin, line cap=round] (-0.05,1) -- (-0.2, 1.12); % hair1
\draw[thick] (0,0) circle [radius=1]; % head
\draw[thin] plot [smooth,tension=1.5] coordinates{(-0.7,0.45) (-0.5,0.52) (-0.4,0.52)}; % leyebrow
\draw[fill=black] (-0.5,0.25) ellipse (0.1 and 0.15);
\draw[thin] plot [smooth,tension=1.5] coordinates{(0.3,0.40) (0.1,0.50) (-0.1,0.50)}; % leyebrow
\draw[fill=black] (0.1,0.20) ellipse (0.1 and 0.15);
\draw[thick] plot [smooth,tension=1.5] coordinates{(-0.75,-0.4) (-0.2,-0.6) (0.3,-0.53)}; % mouth
\draw[thick] (-0.15,-1) .. controls (-0.4,-2.5) .. (-0.5,-4); % torso
\draw[thick] (-0.2,-1.3) -- (0.35, -2.55) -- (1.5, -2.2); % rarm
\draw[thick,rotate around={110:(1.5, -2.2)}] (1.5, -2.4) ellipse (0.1 and 0.2);
\draw[thick] (-0.2,-1.3) -- (-1.55, -2.55) -- (-1.75, -4.1); % rarm
\draw[thick,rotate around={-5:(-1.75, -4.1)}] (-1.75, -4.3) ellipse (0.1 and 0.2);
\draw[thick] (-0.5,-4) -- (0.7, -5.3) -- (1.4,-6.8); % rleg
\draw[thick,rotate around={25:(1.4,-6.8)}] (1.65,-6.8) ellipse (0.25 and 0.1);
\draw[thick] (-0.5,-4) -- (-0.95,-5.8) -- (-2.3,-7); % rleg
\draw[thick,rotate around={-35:(-2.3,-7)}] (-2.05,-7) ellipse (0.25 and 0.1);
}
\newlength\pre@y@max
\newlength\pre@y@min
\newlength\pre@other
\tikzset{
stickman/.pic={
\begin{pgfinterruptboundingbox}
\begin{scope}[opacity=0, local bounding box=pre]
\@stickman
\end{scope}
\path (pre.north);
\pgfgetlastxy{\pre@other}{\pre@y@max}
\path (pre.south);
\pgfgetlastxy{\pre@other}{\pre@y@min}
\pgfmathparse{(\stickman@height - 2*\stickman@y@sep)/(\pre@y@max - \pre@y@min)}
\global\let\temp@scale\pgfmathresult
\end{pgfinterruptboundingbox}
\draw[line width=1pt] let \p1 = (pre.south west), \p2 = (pre.north west), \p3 = (pre.north east) in
let \p{anchor} = ($(\stickman@x@sep,\stickman@y@sep)-\temp@scale*(pre.south west)$) in
let \p{other} = ($2*(\stickman@x@sep,\stickman@y@sep)+\temp@scale*(\p3)-\temp@scale*(\p1)$) in
coordinate (shift) at (\p{anchor})
coordinate (clip) at (\p{other});
\begin{scope}[local bounding box=now]
\draw[line width=1pt] (0, 0) rectangle (clip);
\begin{scope}[scale=\temp@scale, shift=(shift)]
\@stickman
\end{scope}
\end{scope}
\coordinate (-north) at (now.north);
\coordinate (-east) at (now.east);
\coordinate (-west) at (now.west);
\coordinate (-south east) at (now.south east);
}
}
\makeatother
\begin{document}
\begin{tikzpicture}[node distance=0pt]
\pic [stickman height=3cm] (a) at (0, 0) {stickman};
\pic [stickman height=3cm, xshift=1cm, stickman x sep=10pt] (b) at (a-south east) {stickman};
\draw[->, very thick] (a-east) -- (b-west);
\node[above] at (a-north) {Input};
\node[above] at (b-north) {NextStep};
\end{tikzpicture}
\end{document}