14

This is a follow-up question from Use tikz external feature with beamer \only . Andrew's answer there is excellent, and does the job (almost) perfectly.

The rough edge I have found was when I tried to use \tikzsetnextfilename together with it.

Why would I want to do that? Because in beamer, one might need to reorder one's slides, or to add an overlay, etc. In this case, most pictures will need to be regenerated, even if they weren't changed.

What is the problem? The following M(n)WE shows the usual way of using \tikzsetnextfilename.

\documentclass{beamer}

\usepackage{tikz}

\usetikzlibrary{external}

\makeatletter
\tikzset{
  beamer externalizing/.style={%
    execute at end picture={%
      \tikzifexternalizing{%
        \ifbeamer@anotherslide
        \pgfexternalstorecommand{\string\global\string\beamer@anotherslidetrue}%
        \fi
      }{}%
    }%
  },
  external/optimize=false
}
\makeatother

\tikzset{every picture/.style={beamer externalizing}}

\tikzexternalize

\begin{document}

\begin{frame}
  \tikzsetnextfilename{figure}
  \only<1>{Image 1:}
  \only<2>{Image 2:}
  \begin{tikzpicture}
    \only<1>{\node {Overlay 1};}
    \only<2>{\node {Overlay 2};}
  \end{tikzpicture}
\end{frame}

\end{document}

This doesn't work. I'm not pro enough with latex, beamer and tikz mechanics, but I suspect that the problem is tikz externalize trying to generate the two pictures with the same file name.

And indeed, the following code snippet does work.

\documentclass{beamer}

\usepackage{tikz}

\usetikzlibrary{external}

\makeatletter
\tikzset{
  beamer externalizing/.style={%
    execute at end picture={%
      \tikzifexternalizing{%
        \ifbeamer@anotherslide
        \pgfexternalstorecommand{\string\global\string\beamer@anotherslidetrue}%
        \fi
      }{}%
    }%
  },
  external/optimize=false
}
\makeatother

\tikzset{every picture/.style={beamer externalizing}}

\tikzexternalize

\begin{document}

\begin{frame}
  \only<1>{\tikzsetnextfilename{figure-1}}
  \only<2>{\tikzsetnextfilename{figure-2}}
  \only<1>{Image 1:}
  \only<2>{Image 2:}
  \begin{tikzpicture}
    \only<1>{\node {Overlay 1};}
    \only<2>{\node {Overlay 2};}
  \end{tikzpicture}
\end{frame}

\end{document}

Now it is still far from perfect. For example, it requires to know precisely how many overlays are needed for every picture.

Hence the question : is there a better, more natural way of achieving this? If not, is there a way to make this method transparent to the user (so that he doesn't need to count the overlays himself)?

20

You can automatically add the overlay number to the file name using the code from Accessing the current overlay number in beamer. If you only want to do this for some pictures, then use like:

  \tikzsetnextfilename{figure-\overlaynumber}

To add it to every picture you could make it part of the prefix:

\tikzexternalize[prefix=picture-\overlaynumber-]

Using the suffix notation, (\tikzset{external/figure name/.add={}{-\overlaynumber}}) doesn't seem to work as the figure name is overriden by the \tikzsetnextfilename. If you want to automatically add a suffix you'd have to hack \tikzsetnextfilename:

\let\orig@tikzsetnextfilename=\tikzsetnextfilename
\renewcommand\tikzsetnextfilename[1]{\orig@tikzsetnextfilename{#1-\overlaynumber}}

(inside the \makeatletter ... \makeatother bit).

Although the most hackish, this one ends up with the nicest file names so it's the one I've gone for.

\documentclass{beamer}
%\url{https://tex.stackexchange.com/q/119428/86}
\usepackage{tikz}

\usetikzlibrary{external}

\makeatletter
\newcommand*{\overlaynumber}{\number\beamer@slideinframe}
\tikzset{
  beamer externalizing/.style={%
    execute at end picture={%
      \tikzifexternalizing{%
        \ifbeamer@anotherslide
        \pgfexternalstorecommand{\string\global\string\beamer@anotherslidetrue}%
        \fi
      }{}%
    }%
  },
  external/optimize=false
}
\let\orig@tikzsetnextfilename=\tikzsetnextfilename
\renewcommand\tikzsetnextfilename[1]{\orig@tikzsetnextfilename{#1-\overlaynumber}}
\makeatother

\tikzset{every picture/.style={beamer externalizing}}

\tikzexternalize

\begin{document}

\begin{frame}
  \tikzsetnextfilename{figure}
  \only<1>{Image 1:}
  \only<2>{Image 2:}
  \begin{tikzpicture}
    \only<1>{\node {Overlay 1};}
    \only<2>{\node {Overlay 2};}
  \end{tikzpicture}
\end{frame}

\end{document}
  • Awesome, thank you! Note that it also offers a nice workaround to the "problem" you mentioned in the other question, that you need to regenerate all overlays for a picture in case one is changed (that is with the current CTAN version of tikz with the lazy up-to-date check, and assuming you force the regeneration by deleting the appropriate .pdf). – T. Verron Jun 16 '13 at 20:19
  • This is very clever. Maybe it should be emphasized that the \overlaynumber command is not a native command, but is defined in the link given, to keep things together! – Mathias Kure Jun 14 '18 at 23:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.