Animação tikz complexa com beamer

Animação tikz complexa com beamer

Estou usando o tikz para criar uma espécie de animação de cifra Ceasar com o beamer.

Posso conseguir o que quero, mas, como não sou muito habilidoso em tikz, o resultado é um tanto estranho porque é muito lento para compilar: isso é uma grande desvantagem porque dentro de um documento grande com muitos deles ele fica terrivelmente lento.

Meu código é o seguinte (bem, um pequeno exemplo funcional)

\documentclass{beamer}
\usetheme{Berkeley}
\usepackage{graphicx}
\usepackage{ifthen}
\usepackage{tikz}
\tikzset{
  invisible/.style={opacity=0},
  visible on/.style={alt={#1{}{invisible}}},
  alt/.code args={<#1>#2#3}{\alt<#1>{\pgfkeysalso{#2}}{\pgfkeysalso{#3}} 
  },
}
\begin{document}
\begin{frame}
\centering
\begin{tikzpicture}[scale=0.3, every node/.style={scale=0.3}]
 \pgfmathsetmacro{\alphsize}{26}
 \pgfmathsetmacro{\ang}{360/\alphsize}
 \pgfmathsetmacro{\d}{3}
 \pgfmathsetmacro{\op}{98 + \ang/2 - 1.2}
 \pgfmathsetmacro{\e}{\ang + \ang*\d}
 \pgfmathsetmacro{\ep}{\op + \ang*\d}
 \foreach \x in {0,\ang,...,360} {\draw[gray] (\x:8em) -- (\x:12em);}
 \foreach \x [count=\xi] in {A,...,Z} {
  \node[rotate=\ang - \ang*\xi,visible on=<1>]  at (\op - \ang*\xi:11em)     {{\Large \x}};   
  \node[rotate=\ang - \ang*\xi,visible on=<2>]  at (\op - \ang*\xi:11em) {\ifthenelse{\equal{\x}{T}}{\color{green}\Large \x}{\Large \x}};   
  \node[rotate=\ang - \ang*\xi,visible on=<3>]  at (\op - \ang*\xi:11em) {\ifthenelse{\equal{\x}{E}}{\color{green}\Large \x}{\Large \x}};   
  \node[rotate=\ang - \ang*\xi,visible on=<4>]  at (\op - \ang*\xi:11em) {\ifthenelse{\equal{\x}{L}}{\color{green}\Large \x}{\Large \x}};   
  \node[rotate=\ang - \ang*\xi,visible on=<5>]  at (\op - \ang*\xi:11em) {\ifthenelse{\equal{\x}{E}}{\color{green}\Large \x}{\Large \x}};   
  \node[rotate=\ang - \ang*\xi,visible on=<6>]  at (\op - \ang*\xi:11em) {\ifthenelse{\equal{\x}{P}}{\color{green}\Large \x}{\Large \x}};   
  \node[rotate=\ang - \ang*\xi,visible on=<7>]  at (\op - \ang*\xi:11em) {\ifthenelse{\equal{\x}{H}}{\color{green}\Large \x}{\Large \x}};   
  \node[rotate=\ang - \ang*\xi,visible on=<8>]  at (\op - \ang*\xi:11em) {\ifthenelse{\equal{\x}{O}}{\color{green}\Large \x}{\Large \x}};   
  \node[rotate=\ang - \ang*\xi,visible on=<9>]  at (\op - \ang*\xi:11em) {\ifthenelse{\equal{\x}{N}}{\color{green}\Large \x}{\Large \x}};   
  \node[rotate=\ang - \ang*\xi,visible on=<10>] at (\op - \ang*\xi:11em) {\ifthenelse{\equal{\x}{E}}{\color{green}\Large \x}{\Large \x}};   
  \node[rotate=\e - \ang*\xi,visible on=<1>]  at (\ep - \ang*\xi:9em) {{\large \x}};     
  \node[rotate=\e - \ang*\xi,visible on=<2>]  at (\ep - \ang*\xi:9em) {\ifthenelse{\equal{\x}{W}}{\color{red}\large \x}{\large \x}};     
  \node[rotate=\e - \ang*\xi,visible on=<3>]  at (\ep - \ang*\xi:9em) {\ifthenelse{\equal{\x}{H}}{\color{red}\large \x}{\large \x}};     
  \node[rotate=\e - \ang*\xi,visible on=<4>]  at (\ep - \ang*\xi:9em) {\ifthenelse{\equal{\x}{O}}{\color{red}\large \x}{\large \x}};     
  \node[rotate=\e - \ang*\xi,visible on=<5>]  at (\ep - \ang*\xi:9em) {\ifthenelse{\equal{\x}{H}}{\color{red}\large \x}{\large \x}};     
  \node[rotate=\e - \ang*\xi,visible on=<6>]  at (\ep - \ang*\xi:9em) {\ifthenelse{\equal{\x}{S}}{\color{red}\large \x}{\large \x}};     
  \node[rotate=\e - \ang*\xi,visible on=<7>]  at (\ep - \ang*\xi:9em) {\ifthenelse{\equal{\x}{K}}{\color{red}\large \x}{\large \x}};     
  \node[rotate=\e - \ang*\xi,visible on=<8>]  at (\ep - \ang*\xi:9em) {\ifthenelse{\equal{\x}{R}}{\color{red}\large \x}{\large \x}};     
  \node[rotate=\e - \ang*\xi,visible on=<9>]  at (\ep - \ang*\xi:9em) {\ifthenelse{\equal{\x}{Q}}{\color{red}\large \x}{\large \x}};     
  \node[rotate=\e - \ang*\xi,visible on=<10>] at (\ep - \ang*\xi:9em) {\ifthenelse{\equal{\x}{H}}{\color{red}\large \x}{\large \x}};     
}
 \draw[thick] (0cm,0cm) circle(12em);
 \draw[gray] (0cm,0cm) circle(10em);
 \draw[thick] (0cm,0cm) circle(8em);
\end{tikzpicture} 

\bigskip

\centering
\begin{tikzpicture}[every node/.style={scale=0.6}]
  \draw[step=1em,gray,thin] (0em,0em) grid (9em,2em);
  \node at (0.5em,1.5em) {\textcolor<2> {green}T};
  \node at (1.5em,1.5em) {\textcolor<3> {green}E};
  \node at (2.5em,1.5em) {\textcolor<4> {green}L};
  \node at (3.5em,1.5em) {\textcolor<5> {green}E};
  \node at (4.5em,1.5em) {\textcolor<6> {green}P};
  \node at (5.5em,1.5em) {\textcolor<7> {green}H};
  \node at (6.5em,1.5em) {\textcolor<8> {green}O};
  \node at (7.5em,1.5em) {\textcolor<9> {green}N};
  \node at (8.5em,1.5em) {\textcolor<10>{green}E};
  \node[visible on=<2->]  at (0.5em,0.5em) {\textcolor<2> {red}W};
  \node[visible on=<3->]  at (1.5em,0.5em) {\textcolor<3> {red}H};
  \node[visible on=<4->]  at (2.5em,0.5em) {\textcolor<4> {red}O};
  \node[visible on=<5->]  at (3.5em,0.5em) {\textcolor<5> {red}H};
  \node[visible on=<6->]  at (4.5em,0.5em) {\textcolor<6> {red}S};
  \node[visible on=<7->]  at (5.5em,0.5em) {\textcolor<7> {red}K};
  \node[visible on=<8->]  at (6.5em,0.5em) {\textcolor<8> {red}R};
  \node[visible on=<9->]  at (7.5em,0.5em) {\textcolor<9> {red}Q};
  \node[visible on=<10->] at (8.5em,0.5em) {\textcolor<10>{red}H};
\end{tikzpicture}

\end{frame}
\end{document}

A questão é: existe uma maneira mais inteligente de obter o mesmo resultado acima, que será compilado mais rapidamente?

Responder1

Não vejo nenhum problema grave que possa retardar significativamente o seu código. Como recompilar um grande número de imagens complexas do TikZ pode ser muito incômodo, existe uma biblioteca externalque força o TikZ a salvar e, se possível, reutilizar as imagens. Isto se faz do seguinte modo.

\usetikzlibrary{external}
\tikzexternalize

Editar: Como @brad sugere nos comentários, pode ser vantajoso usar \tikzexternalize[prefix=tikz/], para definir uma pasta para as imagens temporárias do TikZ.

Como você está usando a \onlyconstrução do beamer, isso não funciona conforme o esperado, apenas o primeiro quadro é renderizado. Existe, no entanto, um "hack":

Envolva todo o tikzpictureambiente por \only<m-M>onde mestá omínimoe Mé omáximonúmero do quadro referenciado pelos \onlycomandosdentro dea imagem tikz.

Como a [visible on=<m-M>]opção é “equivalente” ao \onlycomando, você pode usá-la assim.

\only<1-10>{%
\begin{tikzpicture}
    \node[visible on=<1>] {};
    % ...
    \node[visible on=<10>] {};
\end{tikzpicture}
}

Eu tentei isso para o seu código e os segundos (e posteriores) tempos de compilação sãomuitomais baixo.

VerUse o recurso externo tikz com o beamer \onlypara mais informações.

O código completo:

\documentclass{beamer}
\usetheme{Berkeley}
\usepackage{graphicx}
\usepackage{ifthen}
\usepackage{tikz}
\tikzset{
  invisible/.style={opacity=0},
  visible on/.style={alt={#1{}{invisible}}},
  alt/.code args={<#1>#2#3}{\alt<#1>{\pgfkeysalso{#2}}{\pgfkeysalso{#3}} 
  },
}

\usetikzlibrary{external}
\tikzexternalize

\begin{document}
\begin{frame}
\centering
\only<1-10>{%
\begin{tikzpicture}[scale=0.3, every node/.style={scale=0.3}]
 \pgfmathsetmacro{\alphsize}{26}
 \pgfmathsetmacro{\ang}{360/\alphsize}
 \pgfmathsetmacro{\d}{3}
 \pgfmathsetmacro{\op}{98 + \ang/2 - 1.2}
 \pgfmathsetmacro{\e}{\ang + \ang*\d}
 \pgfmathsetmacro{\ep}{\op + \ang*\d}
 \foreach \x in {0,\ang,...,360} {\draw[gray] (\x:8em) -- (\x:12em);}
 \foreach \x [count=\xi] in {A,...,Z} {
  \node[rotate=\ang - \ang*\xi,visible on=<1>]  at (\op - \ang*\xi:11em)     {{\Large \x}};   
  \node[rotate=\ang - \ang*\xi,visible on=<2>]  at (\op - \ang*\xi:11em) {\ifthenelse{\equal{\x}{T}}{\color{green}\Large \x}{\Large \x}};   
  \node[rotate=\ang - \ang*\xi,visible on=<3>]  at (\op - \ang*\xi:11em) {\ifthenelse{\equal{\x}{E}}{\color{green}\Large \x}{\Large \x}};   
  \node[rotate=\ang - \ang*\xi,visible on=<4>]  at (\op - \ang*\xi:11em) {\ifthenelse{\equal{\x}{L}}{\color{green}\Large \x}{\Large \x}};   
  \node[rotate=\ang - \ang*\xi,visible on=<5>]  at (\op - \ang*\xi:11em) {\ifthenelse{\equal{\x}{E}}{\color{green}\Large \x}{\Large \x}};   
  \node[rotate=\ang - \ang*\xi,visible on=<6>]  at (\op - \ang*\xi:11em) {\ifthenelse{\equal{\x}{P}}{\color{green}\Large \x}{\Large \x}};   
  \node[rotate=\ang - \ang*\xi,visible on=<7>]  at (\op - \ang*\xi:11em) {\ifthenelse{\equal{\x}{H}}{\color{green}\Large \x}{\Large \x}};   
  \node[rotate=\ang - \ang*\xi,visible on=<8>]  at (\op - \ang*\xi:11em) {\ifthenelse{\equal{\x}{O}}{\color{green}\Large \x}{\Large \x}};   
  \node[rotate=\ang - \ang*\xi,visible on=<9>]  at (\op - \ang*\xi:11em) {\ifthenelse{\equal{\x}{N}}{\color{green}\Large \x}{\Large \x}};   
  \node[rotate=\ang - \ang*\xi,visible on=<10>] at (\op - \ang*\xi:11em) {\ifthenelse{\equal{\x}{E}}{\color{green}\Large \x}{\Large \x}};   
  \node[rotate=\e - \ang*\xi,visible on=<1>]  at (\ep - \ang*\xi:9em) {{\large \x}};     
  \node[rotate=\e - \ang*\xi,visible on=<2>]  at (\ep - \ang*\xi:9em) {\ifthenelse{\equal{\x}{W}}{\color{red}\large \x}{\large \x}};     
  \node[rotate=\e - \ang*\xi,visible on=<3>]  at (\ep - \ang*\xi:9em) {\ifthenelse{\equal{\x}{H}}{\color{red}\large \x}{\large \x}};     
  \node[rotate=\e - \ang*\xi,visible on=<4>]  at (\ep - \ang*\xi:9em) {\ifthenelse{\equal{\x}{O}}{\color{red}\large \x}{\large \x}};     
  \node[rotate=\e - \ang*\xi,visible on=<5>]  at (\ep - \ang*\xi:9em) {\ifthenelse{\equal{\x}{H}}{\color{red}\large \x}{\large \x}};     
  \node[rotate=\e - \ang*\xi,visible on=<6>]  at (\ep - \ang*\xi:9em) {\ifthenelse{\equal{\x}{S}}{\color{red}\large \x}{\large \x}};     
  \node[rotate=\e - \ang*\xi,visible on=<7>]  at (\ep - \ang*\xi:9em) {\ifthenelse{\equal{\x}{K}}{\color{red}\large \x}{\large \x}};     
  \node[rotate=\e - \ang*\xi,visible on=<8>]  at (\ep - \ang*\xi:9em) {\ifthenelse{\equal{\x}{R}}{\color{red}\large \x}{\large \x}};     
  \node[rotate=\e - \ang*\xi,visible on=<9>]  at (\ep - \ang*\xi:9em) {\ifthenelse{\equal{\x}{Q}}{\color{red}\large \x}{\large \x}};     
  \node[rotate=\e - \ang*\xi,visible on=<10>] at (\ep - \ang*\xi:9em) {\ifthenelse{\equal{\x}{H}}{\color{red}\large \x}{\large \x}};     
}
 \draw[thick] (0cm,0cm) circle(12em);
 \draw[gray] (0cm,0cm) circle(10em);
 \draw[thick] (0cm,0cm) circle(8em);
\end{tikzpicture} 
}
\bigskip

\centering
\only<1-10>{%
\begin{tikzpicture}[every node/.style={scale=0.6}]
  \draw[step=1em,gray,thin] (0em,0em) grid (9em,2em);
  \node at (0.5em,1.5em) {\textcolor<2> {green}T};
  \node at (1.5em,1.5em) {\textcolor<3> {green}E};
  \node at (2.5em,1.5em) {\textcolor<4> {green}L};
  \node at (3.5em,1.5em) {\textcolor<5> {green}E};
  \node at (4.5em,1.5em) {\textcolor<6> {green}P};
  \node at (5.5em,1.5em) {\textcolor<7> {green}H};
  \node at (6.5em,1.5em) {\textcolor<8> {green}O};
  \node at (7.5em,1.5em) {\textcolor<9> {green}N};
  \node at (8.5em,1.5em) {\textcolor<10>{green}E};
  \node[visible on=<2->]  at (0.5em,0.5em) {\textcolor<2> {red}W};
  \node[visible on=<3->]  at (1.5em,0.5em) {\textcolor<3> {red}H};
  \node[visible on=<4->]  at (2.5em,0.5em) {\textcolor<4> {red}O};
  \node[visible on=<5->]  at (3.5em,0.5em) {\textcolor<5> {red}H};
  \node[visible on=<6->]  at (4.5em,0.5em) {\textcolor<6> {red}S};
  \node[visible on=<7->]  at (5.5em,0.5em) {\textcolor<7> {red}K};
  \node[visible on=<8->]  at (6.5em,0.5em) {\textcolor<8> {red}R};
  \node[visible on=<9->]  at (7.5em,0.5em) {\textcolor<9> {red}Q};
  \node[visible on=<10->] at (8.5em,0.5em) {\textcolor<10>{red}H};
\end{tikzpicture}
}
\end{frame}
\end{document}

informação relacionada