介绍
很久以前,我开始学习如何使用 TikZ,并创建了一些做工不太好图表。其中一个图表是线性动力系统的状态空间表示。当我发现我可以用 TikZ 制作动画时,我尽力将该图表制作成动画,以解释应该一步一步思考如何绘制和理解该图表。
最近我用新学到的方法重新设计了一些旧图表,并决定制作一些动画,但我注意到我还应该修改如何为它们制作动画,因为它们与我制作的原始绘图不同。
问题
现在到了决策点。在创建节点然后创建它们之间的连接的图表中(下面的 MWE 2),最好的方法是逐步创建这些图表的动画吗?如何在已经读过 TikZ 图表后创建这样的分步动画?
我知道要求“最佳”有点主观和基于意见,但在这种情况下,我只是缺乏信息来决定如何进行,并且需要花费很长时间通过反复试验来了解哪种方法更合适。
“最佳”的标准。
- 在原始 TikZ 上绘制较少的改动
- 允许以(几乎)任何顺序逐步查看图表
- 编译速度快(或者不太长)
背景
我已经看到了使用、创建多页 pdf 和使用的一些可能性uncover
,multido
但\animategraphics
我不知道哪一个最适合我的需求。
- 揭露:使用 Tikz 和 'animate' 包制作动画线/路径
- 多做:如何在 \tikz 中保留 \multiframe 中的前几行?
- 多页 pdf 动画如何绘制像这样的蜘蛛网图?
\animategraphics[<options>]{<frame rate>}{<file basename>}{<first>}{<last>}
animate 包
据我所知,我猜测 uncover
似乎更符合我的标准。
原始图表和动画 - MWE 1
这是我创建动画的第一种方法。它是笨拙,我曾经\ifthenelse
定义过每个步骤中呈现的内容,代码很长,我不知道如何保留已经绘制的内容。真是一团糟。(我甚至不记得我在哪里找到了基于此代码的示例)。
MWE 1 如下:
\documentclass[border=5pt]{standalone}
\usepackage{amsmath,xifthen,tikz,animate}
\usetikzlibrary{calc}
\begin{document}
\begin{animateinline}[poster=last, controls]{1}
\multiframe{8}{ii=0+1}{% ii=0,1,...99 ; rj=9.9,9.8,...,0.0
\begin{tikzpicture}[very thick, every node/.style={font=\LARGE}];
\definecolor{dkg}{rgb}{0,0.5,0};
% ==========
\useasboundingbox (-6,-3) rectangle ++(20,8);
\node[blue, right] at (9.5,-0.5) {\Huge Step:\ii};
\draw (2.5,0) rectangle ++(2,2) coordinate(G) node[pos=0.5] {\Huge{$\int$}};
\node at (-1,-1.5) {
\begin{tabular}{l}
$\dot{x} = A x + B u$ \\
$y = C x + D u$
\end{tabular}
};
\ifthenelse{\ii < 1}{
\draw [-latex, teal] (G)++(0,-1) -- ++(1,0) coordinate(X) node[above]{$x$} -- ++(1,0);
}{
\ifthenelse{\ii < 2}{
\draw [-latex, teal] (G)++(0,-1) -- ++(1,0) coordinate(X) node[above]{$x$} -- ++(1,0);
\draw (1,1) coordinate(S) circle (1/2);
\draw [-latex, orange] (S)++(1/2,0) -- ++(1,0) coordinate(E) node[midway, above]{$\dot{x}$};
}{
\ifthenelse{\ii < 3}{
\draw [-latex, teal] (G)++(0,-1) -- ++(1,0) coordinate(X) node[above]{$x$} -- ++(1,0);
\draw (1,1) coordinate(S) circle (1/2);
\draw [-latex, orange] (S)++(1/2,0) -- ++(1,0) coordinate(E) node[midway, above]{$\dot{x}$};
\draw (2.5,-2.5) coordinate(A) rectangle ++(2*1,2*1) node[pos=0.5]{$A$};
\draw [-latex, teal] (X) -- ++(0,-2.5) -- ++(-1,0);
}{
\ifthenelse{\ii < 4}{
\draw [-latex, teal] (G)++(0,-1) -- ++(1,0) coordinate(X) node[above]{$x$} -- ++(1,0);
\draw (1,1) coordinate(S) circle (1/2);
\draw [-latex, orange] (S)++(1/2,0) -- ++(1,0) coordinate(E) node[midway, above]{$\dot{x}$};
\draw (2.5,-2.5) coordinate(A) rectangle ++(2*1,2*1) node[pos=0.5]{$A$};
\draw [-latex, teal] (X) -- ++(0,-2.5) -- ++(-1,0);
\draw [-latex, cyan] ($(A)+(0,1)$) -| ($(S)+(0,-0.5)$) node[below right]{$+$};
}{
\ifthenelse{\ii < 5}{
\draw [-latex, teal] (G)++(0,-1) -- ++(1,0) coordinate(X) node[above]{$x$} -- ++(1,0);
\draw (1,1) coordinate(S) circle (1/2);
\draw [-latex, orange] (S)++(1/2,0) -- ++(1,0) coordinate(E) node[midway, above]{$\dot{x}$};
\draw (2.5,-2.5) coordinate(A) rectangle ++(2*1,2*1) node[pos=0.5]{$A$};
\draw [-latex, teal] (X) -- ++(0,-2.5) -- ++(-1,0);
\draw [-latex, cyan] ($(A)+(0,1)$) -| ($(S)+(0,-0.5)$) node[below right]{$+$};
\draw (-2.5,0) rectangle ++(2*1,2*1) coordinate(B) node[pos=0.5]{$B$};
\draw [-latex, red] (B)++(0,-1) -- ++(1,0) node[above left]{$+$};
\draw [-latex, dkg] (-4,1) coordinate(u) node[above]{$u$} |- ++(1.5,0);
}{
\ifthenelse{\ii < 6}{
\draw [-latex, teal] (G)++(0,-1) -- ++(1,0) coordinate(X) node[above]{$x$} -- ++(1,0);
\draw (1,1) coordinate(S) circle (1/2);
\draw [-latex, orange] (S)++(1/2,0) -- ++(1,0) coordinate(E) node[midway, above]{$\dot{x}$};
\draw (2.5,-2.5) coordinate(A) rectangle ++(2*1,2*1) node[pos=0.5]{$A$};
\draw [-latex, teal] (X) -- ++(0,-2.5) -- ++(-1,0);
\draw [-latex, cyan] ($(A)+(0,1)$) -| ($(S)+(0,-0.5)$) node[below right]{$+$};
\draw (-2.5,0) rectangle ++(2*1,2*1) coordinate(B) node[pos=0.5]{$B$};
\draw [-latex, red] (B)++(0,-1) -- ++(1,0) node[above left]{$+$};
\draw [-latex, dkg] (-4,1) coordinate(u) node[above]{$u$} |- ++(1.5,0);
\draw (6.5,0) coordinate(C) rectangle ++(2*1,2*1) node[pos=0.5]{$C$};
\draw (10.5,1) coordinate(y) circle (1/2);
\draw [-latex, violet] (y)++(0.5,0) -- ++(1,0) node[above]{$y$};
\draw [-latex, olive] ($(C)+(2*1,1)$) -- ($(y)+(-0.5,0)$) node[above left]{$+$};
}{
\ifthenelse{\ii < 7}{
\draw [-latex, teal] (G)++(0,-1) -- ++(1,0) coordinate(X) node[above]{$x$} -- ++(1,0);
\draw (1,1) coordinate(S) circle (1/2);
\draw [-latex, orange] (S)++(1/2,0) -- ++(1,0) coordinate(E) node[midway, above]{$\dot{x}$};
\draw (2.5,-2.5) coordinate(A) rectangle ++(2*1,2*1) node[pos=0.5]{$A$};
\draw [-latex, teal] (X) -- ++(0,-2.5) -- ++(-1,0);
\draw [-latex, cyan] ($(A)+(0,1)$) -| ($(S)+(0,-0.5)$) node[below right]{$+$};
\draw (-2.5,0) rectangle ++(2*1,2*1) coordinate(B) node[pos=0.5]{$B$};
\draw [-latex, red] (B)++(0,-1) -- ++(1,0) node[above left]{$+$};
\draw [-latex, dkg] (-4,1) coordinate(u) node[above]{$u$} |- ++(1.5,0);
\draw (6.5,0) coordinate(C) rectangle ++(2*1,2*1) node[pos=0.5]{$C$};
\draw (10.5,1) coordinate(y) circle (1/2);
\draw [-latex, violet] (y)++(0.5,0) -- ++(1,0) node[above]{$y$};
\draw [-latex, olive] ($(C)+(2*1,1)$) -- ($(y)+(-0.5,0)$) node[above left]{$+$};
\draw (2.5,2.5) coordinate(D) rectangle ++(2*1,2*1) coordinate(B) node[pos=0.5]{$D$};
\draw [-latex, dkg] ($(u)+(0.5*1,0)$) |- ($(D)+(0,1)$);
\draw [-latex, cyan] ($(D)+(2*1,1)$) -| ($(y)+(0,0.5)$) node[above right]{$+$};
}{
\draw [-latex, teal] (G)++(0,-1) -- ++(1,0) coordinate(X) node[above]{$x$} -- ++(1,0);
\draw (1,1) coordinate(S) circle (1/2);
\draw [-latex, orange] (S)++(1/2,0) -- ++(1,0) coordinate(E) node[midway, above]{$\dot{x}$};
\draw (2.5,-2.5) coordinate(A) rectangle ++(2*1,2*1) node[pos=0.5]{$A$};
\draw [-latex, teal] (X) -- ++(0,-2.5) -- ++(-1,0);
\draw [-latex, cyan] ($(A)+(0,1)$) -| ($(S)+(0,-0.5)$) node[below right]{$+$};
\draw (-2.5,0) rectangle ++(2*1,2*1) coordinate(B) node[pos=0.5]{$B$};
\draw [-latex, red] (B)++(0,-1) -- ++(1,0) node[above left]{$+$};
\draw [-latex, dkg] (-4,1) coordinate(u) node[above]{$u$} |- ++(1.5,0);
\draw (6.5,0) coordinate(C) rectangle ++(2*1,2*1) node[pos=0.5]{$C$};
\draw (10.5,1) coordinate(y) circle (1/2);
\draw [-latex, violet] (y)++(0.5,0) -- ++(1,0) node[above]{$y$};
\draw [-latex, olive] ($(C)+(2*1,1)$) -- ($(y)+(-0.5,0)$) node[above left]{$+$};
\draw (2.5,2.5) coordinate(D) rectangle ++(2*1,2*1) coordinate(B) node[pos=0.5]{$D$};
\draw [-latex, dkg] ($(u)+(0.5*1,0)$) |- ($(D)+(0,1)$);
\draw [-latex, cyan] ($(D)+(2*1,1)$) -| ($(y)+(0,0.5)$) node[above right]{$+$};
\draw [very thick, red] (-3,-3) coordinate(eq) rectangle ++(12,8);
}}}}}}}
\end{tikzpicture}
}
\end{animateinline}
\end{document}
结果如下。
新的动画图表 - MWE 2
这个新图表使用了一些个人本地定义的/.style
s,组织得更好。首先定义节点,然后建立连接。代码很干净,易于更改,比旧代码好得多。但我不知道如何以最佳方式制作动画。
MWE 2 如下:
\documentclass[border=10pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}
\tikzset{addCross/.style n args={6}{
minimum size={#5 mm}, %minimum height=10mm,
path picture={
\draw[#6]
(path picture bounding box.south east) -- (path picture bounding box.north west)
(path picture bounding box.south west) -- (path picture bounding box.north east);
\node at ($(path picture bounding box.south)!0.4!(path picture bounding box.center)$) {#1};
\node at ($(path picture bounding box.west)!0.4!(path picture bounding box.center)$) {#2};
\node at ($(path picture bounding box.north)!0.4!(path picture bounding box.center)$) {#3};
\node at ($(path picture bounding box.east)!0.4!(path picture bounding box.center)$) {#4};
}
},
addCross/.default={}{}{}{}{10}{}
}
\tikzset{mySimpleArrow/.style n args={2}{
>={latex[#1]},
every path/.style={draw=#2}
},
mySimpleArrow/.default={black}{black}
}
\tikzset{myBlockOpacity/.style n args={4}{
every node/.style={rectangle,draw, text=black,
minimum width=#1, minimum height=#2,
fill opacity=#3, text opacity=#4}
},
myBlockOpacity/.default={1cm}{1cm}{0.4}{1}
}
\begin{document}
\begin{tikzpicture}[very thick]
\begin{scope}
\node[circle,draw,addCross={$+$}{$+$}{}{}{10}{black}] (N1) at (1,-0.5) {};
\end{scope}
\begin{scope}[shift={(3.0,-0.5)},myBlockOpacity]
\node[fill=red] (A) at (0,-1.5) {$A$};
\node[fill=green!50!black] (B) at (-4,0) {$B$};
\node[fill=yellow!75!black] (C) at (3,0) {$C$};
\node (I) at (0,0) {$\displaystyle \int$};
\end{scope}
\begin{scope}[mySimpleArrow={blue}{cyan}]
\path[->] (-2.5,-0.5) node[above]{$u$} -- (B);
\path[->] (B) -- (N1);
\path[->] (N1) -- (I) node[midway, above] {$\dot{x}$};
\path[->] (I) -- (4.5,-0.5) coordinate(x) node[above]{$x$} -- (C);
\path[->] (x) |- (A) -| (N1);
\path[->] (C) -- ++(1.5,0) node[above]{$y$};
\end{scope}
\end{tikzpicture}
\end{document}
产生
答案1
定义了一个beamer
类外命令,它指定要显示\uncover
某个对象的帧号。tikzpicture
%\uncover{<current>}{<when>}{...<commands>...}
\newcommand\uncover[3]{\ifnum#1<#2\phantom{#3}\else#3\fi}
它依赖于\phantom{...}
阻止对象被绘制的命令,但会评估坐标定义,甚至 TikZ 的自动边界框计算。这使我们能够引用隐藏对象的节点坐标,而无需对原始代码进行太多更改。
\documentclass[border=10pt]{standalone}
\usepackage{animate}
\usepackage{tikz}
\usetikzlibrary{calc}
\tikzset{addCross/.style n args={6}{
minimum size={#5 mm}, %minimum height=10mm,
path picture={
\draw[#6]
(path picture bounding box.south east) -- (path picture bounding box.north west)
(path picture bounding box.south west) -- (path picture bounding box.north east);
\node at ($(path picture bounding box.south)!0.4!(path picture bounding box.center)$) {#1};
\node at ($(path picture bounding box.west)!0.4!(path picture bounding box.center)$) {#2};
\node at ($(path picture bounding box.north)!0.4!(path picture bounding box.center)$) {#3};
\node at ($(path picture bounding box.east)!0.4!(path picture bounding box.center)$) {#4};
}
},
addCross/.default={}{}{}{}{10}{}
}
\tikzset{mySimpleArrow/.style n args={2}{
>={latex[#1]},
every path/.style={draw=#2}
},
mySimpleArrow/.default={black}{black}
}
\tikzset{myBlockOpacity/.style n args={4}{
every node/.style={rectangle,draw, text=black,
minimum width=#1, minimum height=#2,
fill opacity=#3, text opacity=#4}
},
myBlockOpacity/.default={1cm}{1cm}{0.4}{1}
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%\uncover{<current>}{<when>}{...}
\newcommand\uncover[3]{\ifnum#1<#2\phantom{#3}\else#3\fi}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\begin{document}
\begin{animateinline}[step,controls=step]{1}
\multiframe{13}{i=0+1}{
\begin{tikzpicture}[very thick]
\begin{scope}
\uncover{\i}{4}{\node[circle,draw,addCross={$+$}{$+$}{}{}{10}{black}] (N1) at (1,-0.5) {};}
\end{scope}
\begin{scope}[shift={(3.0,-0.5)},myBlockOpacity]
\uncover{\i}{9}{\node[fill=red] (A) at (0,-1.5) {$A$};}
\uncover{\i}{2}{\node[fill=green!50!black] (B) at (-4,0) {$B$};}
\uncover{\i}{11}{\node[fill=yellow!75!black] (C) at (3,0) {$C$};}
\uncover{\i}{6}{\node (I) at (0,0) {$\displaystyle \int$};}
\end{scope}
\begin{scope}[mySimpleArrow={blue}{cyan}]
\uncover{\i}{1}{\path[->] (-2.5,-0.5) node[above]{$u$} -- (B);}
\uncover{\i}{3}{\path[->] (B) -- (N1);}
\uncover{\i}{5}{\path[->] (N1) -- (I) node[midway, above] {$\dot{x}$};}
\uncover{\i}{7}{\path[->] (I) -- (4.5,-0.5) coordinate(x) node[above]{$x$} -- (C);}
\uncover{\i}{8}{\path[->] (x) |- (A);}
\uncover{\i}{10}{\path[->] (A) -| (N1);}
\uncover{\i}{12}{\path[->] (C) -- ++(1.5,0) node[above]{$y$};}
\end{scope}
\end{tikzpicture}
}
\end{animateinline}
\end{document}
答案2
我不知道这对你来说是否理想。因为我更改了你的一些tikz
代码,以便对每个路径使用绝对坐标。这样,每个单独的路径都可以在不参考其他路径中的坐标的情况下绘制。你可以自由决定将哪条路径包含在哪一帧中。使用路径\ifnum\i>'some frame number'
前面的 来决定此路径是否将包含在下一帧中(某个帧号+1)。这是代码:
\documentclass[border=10pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}
\usepackage{animate}
\tikzset{addCross/.style n args={6}{
minimum size={#5 mm}, %minimum height=10mm,
path picture={
\draw[#6]
(path picture bounding box.south east) -- (path picture bounding box.north west)
(path picture bounding box.south west) -- (path picture bounding box.north east);
\node at ($(path picture bounding box.south)!0.4!(path picture bounding box.center)$) {#1};
\node at ($(path picture bounding box.west)!0.4!(path picture bounding box.center)$) {#2};
\node at ($(path picture bounding box.north)!0.4!(path picture bounding box.center)$) {#3};
\node at ($(path picture bounding box.east)!0.4!(path picture bounding box.center)$) {#4};
}
},
addCross/.default={}{}{}{}{10}{}
}
\tikzset{mySimpleArrow/.style n args={2}{
>={latex[#1]},
every path/.style={draw=#2}
},
mySimpleArrow/.default={black}{black}
}
\tikzset{myBlockOpacity/.style n args={4}{
every node/.style={rectangle,draw, text=black,
minimum width=#1, minimum height=#2,
fill opacity=#3, text opacity=#4}
},
myBlockOpacity/.default={1cm}{1cm}{0.4}{1}
}
\begin{document}
\begin{animateinline}[autoplay,loop,poster=last, controls]{1}
\multiframe{13}{i=0+1}{
\begin{tikzpicture}[line width=1pt]
\fill [transparent] (-3,0.5) rectangle (8.5,-3);% at frame 1 (when i=0) just draw a transparent background
\ifnum\i>0\node (step) at (6,-2.5) {Step \i};\fi % start from frame 2 there will be label "step \i"
\begin{scope}
\ifnum\i>3\node[circle,draw,addCross={$+$}{$+$}{}{}{10}{black}] (N1) at (1,-0.5) {};\fi
\end{scope}
\begin{scope}[myBlockOpacity]
\ifnum\i>8\node[fill=red] (A) at (3,-2) {$A$};\fi
\ifnum\i>1\node[fill=green!50!black] (B) at (-1,-0.5) {$B$};\fi
\ifnum\i>10\node[fill=yellow!75!black] (C) at (6,-0.5) {$C$};\fi
\ifnum\i>5\node (I) at (3,-0.5) {$\displaystyle \int$};\fi
\end{scope}
\begin{scope}[mySimpleArrow={blue}{cyan}]
\ifnum\i>0\path[->] (-2.5,-0.5) node[above]{$u$} -- ($(-1.5,-0.5)-(0.5pt,0)$);\fi
\ifnum\i>2\path[->] ($(-0.5,-0.5)+(0.5pt,0)$) -- ($(0.5,-0.5)-(0.5pt,0)$);\fi
\ifnum\i>4\path[->] ($(1.5,-0.5)+(0.5pt,0)$) -- ($(2.5,-0.5)-(0.5pt,0)$) node[midway, above] {$\dot{x}$};\fi
\ifnum\i>6\path[->] ($(3.5,-0.5)+(0.5pt,0)$) -- ($(4.5,-0.5)-(0.5pt,0)$) coordinate(x) node[above]{$x$} -- ($(5.5,-0.5)-(0.5pt,0)$);\fi
\ifnum\i>7\path (4.5,-0.5) |- ($(3.5,-2)+(0.5pt,0)$);\fi
\ifnum\i>9\path[->] ($(2.5,-2)-(0.5pt,0)$) -| ($(1,-1)-(0,0.5pt)$);\fi
\ifnum\i>11\path[->] ($(6.5,-0.5)+(0.5pt,0)$) -- ++(1.5,0) node[above]{$y$};\fi
\end{scope}
\end{tikzpicture}
}
\end{animateinline}
\end{document}
动画效果:
答案3
还有一个建议:
- 复制动画,就像在 MWE 中所做的那样
- 简化元素
tikzpicture
样式 - 更短更简单的代码
\documentclass[border=2mm]{standalone}
\usepackage{amsmath,tikz,animate}
\usetikzlibrary{fit,
positioning,
quotes}
\newcommand\ppbb{path picture bounding box}
\tikzset{
arr/.style = {color=#1, very thick, -latex},
box/.style = {draw, very thick, fill=#1!30,
minimum size=16mm, font=\Huge},
FIT/.style = {draw=red, thick, densely dashed,
fit=#1, inner sep=3mm, node contents={}},
sum/.style = {circle, draw, very thick, minimum size=10mm,
path picture={
\draw[thick] (\ppbb.north west) -- (\ppbb.south east)
(\ppbb.south west) -- (\ppbb.north east);
},
node contents={} },
every node/.append style = {inner sep=2pt},
}
\begin{document}
\begin{animateinline}[loop, controls]{2}
\multiframe{9}{ii=0+1}{
\begin{tikzpicture}[
node distance = 3mm and 12mm
]
%
\pgfmathsetmacro{\jj}{int(\ii-1)}
\path (-7,3.3) rectangle ++(14,-6.6);
%
\ifnum\ii > 1
\path (-7,3.3) rectangle ++(14,-6.6)
node[above left=6mm and 12mm,
font=\huge, text=blue] {Step \jj};
%
\node (int) [box=white] {$\int$};
\draw [arr=teal] (int.east) to["$x$"] ++ (1.2,0) coordinate (X);
\path (int) -- coordinate (x) (X);
%
\node (S1) [sum, left=of int];
\draw [arr=orange] (S1) to["$\dot{x}$"] (int);
\fi
\ifnum\ii > 2
\node (A) [box=orange, below=of int] {$A$};
\draw [arr=teal] (x) |- (A);
\fi
\ifnum\ii > 3
\draw [arr=cyan] (A) -| (S1.south) node[above] {$+$};
\fi
\ifnum\ii > 4
\node (B) [box=red, left=of S1] {$B$};
\path (B.west) -- coordinate (d) ++ (-1,0) coordinate (in);
\draw [arr=teal] (in) to[pos=0.2,"$u$"] (B);
\draw [arr=red] (B) -- (S1.west) node[right] {$+$};
\fi
\ifnum\ii > 5
\node (C) [box=olive, right=of int] {$C$};
\node (S2) [sum, right=of C];
\draw [arr=olive] (C) to["$y$"] (S2);
\draw [arr=violet] (S2.east) to["$y$"] ++ (1,0);
\fi
\ifnum\ii > 6
\node (D) [box=cyan, above=of int] {$D$};
\draw [arr=teal] (d) |- (D);
\draw [arr=teal] (D) -| (S2.north) node[below] {$+$};
\fi
\ifnum\ii > 7
\node [FIT=(B) (D) (S2) (A),
label={[anchor=south west, inner sep=6mm]%
south west:$\begin{aligned}
\dot{x} & = Ax + Bu\\
y & = Cx + Du
\end{aligned}$}];
\fi
\end{tikzpicture}
}
\end{animateinline}
\end{document}
编辑:最后一步。
附录(题外话): 我将改变问题中 MWE 1 中显示的控制方案元素的“揭示”顺序。这需要稍长一点的图像代码。
\documentclass[border=3.131592]{standalone}
\usepackage{amsmath,tikz,animate}
\usetikzlibrary{arrows.meta,
fit,
positioning,
quotes}
\newcommand\ppbb{path picture bounding box}
\tikzset{
arr/.style = {draw=#1, very thick, -Straight Barb},
box/.style = {draw=#1, very thick, fill=#1!30,
minimum size=13mm, font=\Huge},
FIT/.style = {draw=red, thick, densely dashed, semitransparent,
fit=#1, inner sep=3mm, node contents={}},
sum/.style = {circle, draw, very thick, fill=#1, minimum size=10mm,
path picture={
\draw[thick] (\ppbb.north west) -- (\ppbb.south east)
(\ppbb.south west) -- (\ppbb.north east);
},
node contents={} },
every node/.append style = {inner sep=2pt},
}
\begin{document}
\begin{animateinline}[loop, controls]{2}
\multiframe{8}{ii=0+1}{
\begin{tikzpicture}[
node distance = 5mm and 15mm
]
%
\pgfmathsetmacro{\jj}{int(\ii-1)}
\path (-5.5,3) rectangle ++(15.5,-6);
%
\ifnum\ii > 1
\path (-5.5,3) rectangle ++(15.5,-6)
node[above left, text=blue] {Step \jj};
%
\coordinate (Ia);
\node (I) [box=red, right=of Ia] {$\int$};
\coordinate[right=of I] (Ib);
\path[arr=red] (Ia) to["$\dot{x}$"] (I);
\path[arr=red] (I) to[name=d, "$x$"] (Ib);
\path (I) -- coordinate (a) (Ib);
\fi
\ifnum\ii > 2
\node (S1) [sum=orange, left=of I];
\coordinate[left=of S1] (Bb);
\node (A) [box=orange, below=of I] {$A$};
\path [arr=orange] (Bb) to["$v$"] (S1.west) node[right] {$+$};
\path [arr=orange] (a) |- (A);
\path [arr=orange] (A) -| (S1.south)
node[above] {$+$}
node[pos=0.75,right] {$Ax$};
\fi
\ifnum\ii > 3
\node (B) [box=teal, left=of S1] {$B$};
\coordinate[left=of B] (in);
\path [arr=teal] (in) to[pos=0.2,"$u$"] (B);
\path (in) -- coordinate (d) (B);
\path (B) to["$v=Bu$" '] (S1);
\fi
\ifnum\ii > 4
\node (C) [box=olive, right=of I] {$C$};
\coordinate[right=of C] (c);
\draw [arr=olive] (C) to["$Cx$"] (c);
\fi
\ifnum\ii > 5
\node (S2) [sum=cyan, right=of C];
\coordinate[right=of S2] (out);
\path [arr=olive] (S2) to["$y$"] (out);
\path (I) -- (S2.west) node[right] {$+$};
\node (D) [box=cyan, above=of I] {$D$};
\path [arr=cyan] (d) |- (D);
\path [arr=cyan] (D) -| (S2.north)
node[below] {$+$}
node[pos=0.75,right] {$Du$};
\fi
\ifnum\ii > 6
\node [FIT=(B) (I) (C) (A),
label={[anchor=south west, inner sep=3mm]%
south west:$\begin{aligned}
\dot{x} & = Ax + Bu\\
y & = Cx
\end{aligned}$}];
\fi
\end{tikzpicture}
}
\end{animateinline}
\end{document}
用同样的方法你可以绘制 MWE 2 中所示的第二个方案:
\documentclass[border=3.131592]{standalone}
\usepackage{amsmath,tikz,animate}
\usetikzlibrary{arrows.meta,
fit,
positioning,
quotes}
\newcommand\ppbb{path picture bounding box}
\tikzset{
arr/.style = {draw=#1, very thick, -Straight Barb},
box/.style = {draw=#1, very thick, fill=#1!30,
minimum size=13mm, font=\Huge},
FIT/.style = {draw=red, thick, densely dashed, semitransparent,
fit=#1, inner sep=3mm, node contents={}},
sum/.style = {circle, draw, very thick, fill=#1, minimum size=10mm,
path picture={
\draw[thick] (\ppbb.north west) -- (\ppbb.south east)
(\ppbb.south west) -- (\ppbb.north east);
},
node contents={} },
every node/.append style = {inner sep=2pt},
}
\begin{document}
\begin{animateinline}[loop, controls]{2}
\multiframe{6}{ii=0+1}{
\begin{tikzpicture}[
node distance = 5mm and 15mm
]
\draw (-5.5,1) rectangle ++(12.75,-3.75);
%
\ifnum\ii > 1
\coordinate (Ia);
\node (I) [box=red, right=of Ia] {$\int$};
\coordinate[right=of I] (Ib);
\path[arr=red] (Ia) to["$\dot{x}$"] (I);
\path[arr=red] (I) to[name=d, "$x$"] (Ib);
\path (I) -- coordinate (a) (Ib);
\fi
\ifnum\ii > 2
\node (S1) [sum=orange, left=of I];
\coordinate[left=of S1] (Bb);
\node (A) [box=orange, below=of I] {$A$};
\path [arr=orange] (Bb) to["$v$"] (S1.west) node[right] {$+$};
\path [arr=orange] (a) |- (A);
\path [arr=orange] (A) -| (S1.south)
node[above] {$+$}
node[pos=0.75,right] {$Ax$};
\fi
\ifnum\ii > 3
\node (B) [box=teal, left=of S1] {$B$};
\coordinate[left=of B] (in);
\path [arr=teal] (in) to[pos=0.2,"$u$"] (B);
\path (in) -- coordinate (d) (B);
\path (B) to["$v=Bu$" '] (S1);
\fi
\ifnum\ii > 4
\node (C) [box=olive, right=of I] {$C$};
\coordinate[right=of C] (c);
\draw [arr=olive] (C) to["$Cx$"] (c);
\node[below=of B] {$\begin{aligned}
\dot{x} & = Ax + Bu\\
y & = Cx
\end{aligned}$};
\fi
\end{tikzpicture}
}
\end{animateinline}
\end{document}
最后一步给出: