[修订版本旨在使 MWE 更加现实]
我有两个相关数字不同宽度tikzpicture
在使用环境pgfplots
和相关环境绘制的环境中axis
。图片当前是为 beamer 文档类绘制的,因此能够利用命令\only
为各种操作建立顺序。具体来说,这种顺序是必要的,因为每张图片都利用了从前一帧的另一张图片中提取的一些信息:这就是在图片之间建立链接的原因。具体来说,每张图片都利用了从前一张图片中提取的一些坐标分量,并且至少一些这些坐标是通过intersections
库确定的。
由于该命令的作用,这一切在 beamer 中运行良好\only
。
是否有一种相对简单的方法可以在非投影仪文档类中重现相同的机制article
?
我已经查阅了很多相关的问答(例如这而且当然这),但我无法从那里开始找到任何解决方案。我认为我的编码技能不足以独自完成它。此外,我查阅了软件包animate
文档,但它对当前问题的可能解决方案(如果有的话)似乎非常复杂。最后,我考虑将每张图片外部化并导出到 pdf,然后在需要时包含它们的最终帧。不幸的是,当必须制作和包含许多图片时,图片的宽度不均匀使得这种解决方案几乎不可行。
\documentclass{beamer}
\usepackage[mode=buildnew]{standalone}
\usepackage{tikz,pgfplots}
\usetikzlibrary{intersections}
% Coordinate extraction
% from: https://tex.stackexchange.com/questions/420498/extract-convert-store-and-reuse-x-y-coordinate-components
\newlength{\lenx}
\newlength{\plotwidth}
\newlength{\leny}
\newlength{\plotheight}
\newcommand{\getvalue}[1]{\pgfkeysvalueof{/pgfplots/#1}}
\newcommand{\Getxycoords}[3]% #1 = node name, #2 x coordinate, #2 y coordinate
{\pgfplotsextra{%
\pgfextractx{\lenx}{\pgfpointdiff{\pgfplotspointaxisxy{0}{0}}{\pgfpointanchor{#1}{center}}}%
\pgfextractx{\plotwidth}{\pgfpointdiff{\pgfplotspointaxisxy{\getvalue{xmin}}{0}}%
{\pgfplotspointaxisxy{\getvalue{xmax}}{0}}}%
\pgfextracty{\leny}{\pgfpointdiff{\pgfplotspointaxisxy{0}{0}}{\pgfpointanchor{#1}{center}}}%
\pgfextracty{\plotheight}{\pgfpointdiff{\pgfplotspointaxisxy{0}{\getvalue{ymin}}}%
{\pgfplotspointaxisxy{0}{\getvalue{ymax}}}}%
\pgfmathsetmacro{\myx}{\lenx*(\getvalue{xmax}-\getvalue{xmin})/\plotwidth}%
\pgfmathsetmacro{\myy}{\leny*(\getvalue{ymax}-\getvalue{ymin})/\plotheight}%
\xdef#2{\myx}%
\xdef#3{\myy}%
% \typeout{\myx,\myy} <- for debugging
}%
}
\begin{document}
\begin{frame}
\centering
\begin{tikzpicture}[baseline=(current bounding box.north),trim axis left,trim axis right]
\begin{axis}[scale=0.6,clip=false,ytick={0}]
\addplot [name path=f,smooth,domain=-20:20] {1+0.5*x} node [anchor=north,yshift=-2mm] {$f(x)$};
\addplot [name path=h,smooth,domain=-20:20] {8+1*x} node [anchor=south,yshift=-2mm] {$h(x)$};
\only<2->{
\path [name intersections={of=f and h,by={A}}] node [anchor=south] at (A) {$A$}; %Assign point A
\Getxycoords{A}{\Ax}{\Ay};
\draw [fill=red] (A) circle (2pt);
}
\only<4->{
\node (C) at (axis cs:{(\By-1)/0.5},\By) {}; %Get point C given point B
\Getxycoords{C}{\Cx}{\Cy};
\draw [fill=red] (C) circle (2pt) node [anchor=south] {C};
\draw [dashed] (axis cs:\Cx,\pgfkeysvalueof{/pgfplots/ymin}) -- (C) -- (axis cs:\pgfkeysvalueof{/pgfplots/xmin},\Cy) node [anchor=east] {$y$-component of $C$};
}
\end{axis}
\end{tikzpicture}
\begin{tikzpicture}[baseline=(current bounding box.north),trim axis left,trim axis right]
\begin{axis}[scale=0.6,clip=true,ytick={0}]
\addplot [name path=g,smooth,domain=-20:20] {1+0.6*x} node [anchor=north,yshift=-2mm] {$g(x)$};
\only<3->{
\node (B) at (axis cs:\Ax,{1+0.6*\Ax}) {}; %Get point B given point A
\Getxycoords{B}{\Bx}{\By};
\draw [fill=red] (B) circle (2pt) node [anchor=south] {B};
}
\end{axis}
\end{tikzpicture}
\end{frame}
\end{document}
答案1
新的答案(针对修改后的问题)
因此,当主要问题是由于边界框大小不同而对齐不同的图时,一种解决方案是将所有环境放入axis
一个tikzpicture
环境中并相应地对齐axis
环境。我在这里仅针对两个环境进行了演示axis
,但我认为以此为起点,您可以axis
自行创建其他环境。
有关详细信息,请查看代码中的注释
% used PGFPlots v1.16
\documentclass[border=5pt]{standalone}
\usepackage{pgfplots}
\usetikzlibrary{intersections}
% Coordinate extraction from
% <https://tex.stackexchange.com/a/426245/95441>
% #1: node name
% #2: output macro name: x coordinate
% #3: output macro name: y coordinate
\newcommand{\Getxycoords}[3]{%
\pgfplotsextra{%
\pgfplotspointgetcoordinates{(#1)}%
\global\pgfkeysgetvalue{/data point/x}{#2}%
\global\pgfkeysgetvalue{/data point/y}{#3}%
}%
}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
% name the plot, so we later can align the second `axis' environment
% relative to this one
name=top plot,
%
clip mode=individual, % <-- changed from `clip=false'
ytick={0},
domain=-20:20,
]
\addplot [name path=f] {1+0.5*x} node [below=2mm] {$f(x)$};
\addplot [name path=h] {8+1*x} node [above] {$h(x)$};
% \only<2->{
\path [
name intersections={
of=f and h,
by={A},
},
] node [anchor=south] at (A) {$A$};
\Getxycoords{A}{\Ax}{\Ay};
\draw [fill=red] (A) circle (2pt);
% }
% add node (B) to this plot, too
\node (B) at (axis cs:\Ax,{1+0.6*\Ax}) {};
\Getxycoords{B}{\Bx}{\By};
% \only<4->{
\node (C) at (axis cs:{(\By-1)/0.5},\By) {};
\Getxycoords{C}{\Cx}{\Cy};
\draw [fill=red] (C) circle (2pt) node [above] {C};
\draw [dashed] (axis cs:\Cx,\pgfkeysvalueof{/pgfplots/ymin})
-- (C)
-- (axis cs:\pgfkeysvalueof{/pgfplots/xmin},\Cy)
node [left] {$y$-component of $C$};
% }
\end{axis}
% don't end the `tikzpicture' environment here, but add the other plots
% as well
\begin{axis}[
% align this `axis' environment relative to the top one
at={(top plot.below south west)},
anchor=above north west,
yshift=-2ex,
%
ytick={0},
domain=-20:20,
]
\addplot [name path=g] {1+0.6*x} node [below=2mm] {$g(x)$};
% \only<3->{
\node (B) at (axis cs:\Ax,{1+0.6*\Ax}) {};
% \Getxycoords{B}{\Bx}{\By};
\draw [fill=red] (B) circle (2pt) node [above] {B};
% }
\end{axis}
\end{tikzpicture}
\end{document}
旧答案(针对修订版 2)
如果您只需要创建单个图,那么有一种更简单的方法来确定/设置给定示例中的点坐标,因为可以根据坐标(A)直接计算所有坐标。
% used PGFPlots v1.15
\documentclass[border=5pt]{standalone}
\usepackage{pgfplots}
\pgfmathsetmacro{\Ax}{2}
\pgfmathsetmacro{\Ay}{1+0.5*2}
\pgfmathsetmacro{\Bx}{\Ax}
\pgfmathsetmacro{\By}{2+2*\Ax}
\pgfmathsetmacro{\Cx}{(\By-1)/0.5}
\pgfmathsetmacro{\Cy}{\By}
\begin{document}
\begin{tikzpicture}
\begin{axis}
\addplot [smooth,domain=-20:20] {1+0.5*x} node [below=2mm] {$f(x)$};
\node (A) at (axis cs:\Ax,\Ay) {};
\draw [fill=red] (A) circle (2pt) node [above] {A};
\end{axis}
\end{tikzpicture}
\begin{tikzpicture}
\begin{axis}
\addplot [smooth,domain=-5:5] {2+2*x} node [below=2mm] {$g(x)$};
\node (B) at (axis cs:\Bx,\By) {};
\draw [fill=red] (B) circle (2pt) node [above] {B};
\end{axis}
\end{tikzpicture}
\begin{tikzpicture}
\begin{axis}
\addplot [smooth,domain=-20:20] {1+0.5*x} node [below=2mm] {$f(x)$};
\node (A) at (axis cs:\Ax,\Ay) {};
\draw [fill=red] (A) circle (2pt) node [above] {A};
\node (C) at (axis cs:\Cx,\Cy) {};
\draw [fill=red] (C) circle (2pt) node [above] {C};
\end{axis}
\end{tikzpicture}
\end{document}
答案2
Beamer 叠加层可以使用 PDF 图层 (OCG) 来近似。only{<...>}{}
使用与 OCG 关联的嵌套 TikZ 范围进行替换。
基于 S. Pinnows 代码版本。
% used PGFPlots v1.15
\documentclass[border=5pt]{standalone}
%\documentclass[border=5pt]{article}
\usepackage{pgfplots}
\usepackage[tikz]{ocgx2}
\pgfplotsset{compat=1.15}
\usetikzlibrary{intersections}
% Coordinate extraction
% from: https://tex.stackexchange.com/questions/420498/extract-convert-store-and-reuse-x-y-coordinate-components
\newlength{\lenx}
\newlength{\plotwidth}
\newlength{\leny}
\newlength{\plotheight}
\newcommand{\getvalue}[1]{\pgfkeysvalueof{/pgfplots/#1}}
\newcommand{\Getxycoords}[3]% #1 = node name, #2 x coordinate, #2 y coordinate
{\pgfplotsextra{%
\pgfextractx{\lenx}{\pgfpointdiff{\pgfplotspointaxisxy{0}{0}}{\pgfpointanchor{#1}{center}}}%
\pgfextractx{\plotwidth}{\pgfpointdiff{\pgfplotspointaxisxy{\getvalue{xmin}}{0}}%
{\pgfplotspointaxisxy{\getvalue{xmax}}{0}}}%
\pgfextracty{\leny}{\pgfpointdiff{\pgfplotspointaxisxy{0}{0}}{\pgfpointanchor{#1}{center}}}%
\pgfextracty{\plotheight}{\pgfpointdiff{\pgfplotspointaxisxy{0}{\getvalue{ymin}}}%
{\pgfplotspointaxisxy{0}{\getvalue{ymax}}}}%
\pgfmathsetmacro{\myx}{\lenx*(\getvalue{xmax}-\getvalue{xmin})/\plotwidth}%
\pgfmathsetmacro{\myy}{\leny*(\getvalue{ymax}-\getvalue{ymin})/\plotheight}%
\xdef#2{\myx}%
\xdef#3{\myy}%
% \typeout{\myx,\myy} <- for debugging
}}%
\begin{document}
\begin{tikzpicture}
\begin{axis}[
% name the plot, so we later can align the second `axis' environment
% relative to this one
name=top plot,
%
clip mode=individual, % <-- changed from `clip=false'
ytick={0},
domain=-20:20,
]
\addplot [name path=f] {1+0.5*x} node [below=2mm] {$f(x)$};
\addplot [name path=h] {8+1*x} node [above] {$h(x)$};
\begin{scope}[ocg={ref=2,name=2,status=invisible}]
% \only<2->{
\path [
name intersections={
of=f and h,
by={A},
},
] node [anchor=south] at (A) {$A$};
\Getxycoords{A}{\Ax}{\Ay};
\draw [fill=red] (A) circle (2pt);
% }
\end{scope}
% add node (B) to this plot, too
\node (B) at (axis cs:\Ax,{1+0.6*\Ax}) {};
\Getxycoords{B}{\Bx}{\By};
\begin{scope}[ocg={ref=2,name=2,status=invisible}]
\begin{scope}[ocg={ref=3,name=3,status=invisible}]
\begin{scope}[ocg={ref=4,name=4,status=invisible}]
% \only<4->{
\node (C) at (axis cs:{(\By-1)/0.5},\By) {};
\Getxycoords{C}{\Cx}{\Cy};
\draw [fill=red] (C) circle (2pt) node [above] {C};
\draw [dashed] (axis cs:\Cx,\pgfkeysvalueof{/pgfplots/ymin})
-- (C)
-- (axis cs:\pgfkeysvalueof{/pgfplots/xmin},\Cy)
node [left] {$y$-component of $C$};
% }
\end{scope}\end{scope}\end{scope}
\end{axis}
% don't end the `tikzpicture' environment here, but add the other plots
% as well
\begin{axis}[
% align this `axis' environment relative to the top one
at={(top plot.below south west)},
anchor=above north west,
yshift=-2ex,
%
ytick={0},
domain=-20:20,
]
\addplot [name path=g] {1+0.6*x} node [below=2mm] {$g(x)$};
\begin{scope}[ocg={ref=2,name=2,status=invisible}]
\begin{scope}[ocg={ref=3,name=3,status=invisible}]
% \only<3->{
\node (B) at (axis cs:\Ax,{1+0.6*\Ax}) {};
% \Getxycoords{B}{\Bx}{\By};
\draw [fill=red] (B) circle (2pt) node [above] {B};
% }
\end{scope}\end{scope}
\end{axis}
\path node [show ocg={2}, draw, anchor=north west, name=A] at (0,-7) {A}
node [show ocg={3}, draw, anchor=west, right of=A, name=B] {B}
node [show ocg={4}, draw, anchor=west, right of=B, name=C] {C}
node [hide ocg={2 3 4}, draw, anchor=west, right of=C] {Clear};
\end{tikzpicture}
\end{document}