31

I'm looking to use the animate package in beamer to display animated graphics to my class, and I was wondering if it'd be possible for the animation to work on their Chromebooks. It seems Adobe isn't supported on ChromeOS, so is there any other alternative?

This question seems relevant, but I don't have any movie files or gifs, just what I've made using the animate package in LaTeX.

I understand this is quite likely not possible, but any help would be much appreciated.

3
  • Per the animate documentation the other viewer which can run the animation is PDF-XChange Viewer Commented Mar 26, 2015 at 2:26
  • pdf-xchange viewer did not run my animations inside PDF. Only Adobe PDF reader did.
    – Nasser
    Commented Apr 24, 2018 at 2:43
  • KDE Okular supports animations made with pkg animate.
    – AlexG
    Commented Feb 15, 2022 at 17:01

1 Answer 1

48

1 beamer class document in SVG format

Think about giving up the PDF format in favour of SVG.

Animations run in all contemporary Web browsers, while Blink-based ones (Chromium, Chrome, Edge, Opera) have the best performance. Also run on mobile devices.

With SVG as output format, video and YouTube embeds are possible too, using package media4svg; see: MP4 in presentation in a non-broken way . And even animated Gif.

Click the image to start presentation in the Web browser and press F11 for full-screen. Navigate through slides with PgUp and PgDown, mouse left or right click, or mouse wheel.



Compile the example code with

latex svgbeamer
latex svgbeamer
dvisvgm --zoom=-1 --font-format=woff2 --bbox=papersize --page=1- --linkmark=none svgbeamer

Example code svgbeamer.tex:

\documentclass[dvisvgm,hypertex,aspectratio=169]{beamer}
\usefonttheme{serif}

\usepackage{animate}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% slide navigation via keyboard and mouse left-or-right-click/mouse wheel,
% mouse cursor autohide on idle; navigation symbols <--, -->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\usepackage{fontawesome5}
\setbeamertemplate{navigation symbols}{}
\AddToHook{shipout/before}{\xdef\currentPageNumber{\inteval{\ReadonlyShipoutCounter+1}}}
\AddToHook{shipout/foreground}{%
  \put(0,0){%
    \raisebox{-\dimexpr\height+0.5ex\relax}[0pt][0pt]{\makebox[\paperwidth][r]{%
      \normalsize\color{structure!40!}%
      \ifnum\currentPageNumber>1%
        \href{\jobname-\zeroPad{\PreviousTotalPages}{\the\numexpr\currentPageNumber-1\relax}.svg}{\faArrowLeft}%
      \else%
        \textcolor{lightgray}{\faArrowLeft}%
      \fi\hspace{0.5ex}%
      \ifnum\currentPageNumber<\PreviousTotalPages%
        \href{\jobname-\zeroPad{\PreviousTotalPages}{\the\numexpr\currentPageNumber+1\relax}.svg}{\faArrowRight}%
      \else%
        \textcolor{lightgray}{\faArrowRight}%
      \fi%
      \hspace{0.5ex}%
    }}%
  }%
  \special{dvisvgm:raw
    <style>svg{cursor: none}</style>%
    <defs>%
    <script type="text/javascript">%
    <![CDATA[%
      var cursorTimer;%
      var downOnLink=false;%
      var downOnRoot=false;%
      function islink(tg){return (tg.tagName=='a') ? true : tg.parentNode ? islink(tg.parentNode) : false;};%
      function ismmedia(tg){return (tg.tagName=='video'||tg.tagName=='audio') ? true : tg.parentNode ? ismmedia(tg.parentNode) : false;};%
      document.addEventListener('mousemove', function(e){%
        if(islink(e.target)||ismmedia(e.target)||e.target.getAttribute('class')=='annot'){%
          e.target.style.cursor='pointer';}else{e.target.style.cursor='default';}%
        try{clearTimeout(cursorTimer);}catch(err){};%
        cursorTimer=setTimeout(function(){e.target.style.cursor='none';},3000);%
      });%
      window.addEventListener('contextmenu', function(e){% capture right click
        if(!islink(e.target)&&!ismmedia(e.target)) e.preventDefault();%
      });%
      document.addEventListener('mousedown', function(e){%
        if(islink(e.target)||ismmedia(e.target)) downOnLink=true;%
        else downOnRoot=true;%
      });%
      document.addEventListener('mouseup', function(e){%
        if(downOnLink||!downOnRoot){downOnLink=false;return;}%
        downOnRoot=false;%
        \ifnum\currentPageNumber<\PreviousTotalPages
          if(!e.shiftKey&&e.button==0) document.location.replace('\jobname-\zeroPad{\PreviousTotalPages}{\the\numexpr\currentPageNumber+1\relax}.svg');%
        \fi%
        \ifnum\currentPageNumber>1
          if(e.shiftKey||e.button>1) document.location.replace('\jobname-\zeroPad{\PreviousTotalPages}{\the\numexpr\currentPageNumber-1\relax}.svg');%
        \fi%
      });%
      document.addEventListener('wheel', function(e){%
        \ifnum\currentPageNumber<\PreviousTotalPages
          if(e.deltaY>0){%
            document.location.replace('\jobname-\zeroPad{\PreviousTotalPages}{\the\numexpr\currentPageNumber+1\relax}.svg');%
          }%
        \fi%
        \ifnum\currentPageNumber>1
          if(e.deltaY<0){%
            document.location.replace('\jobname-\zeroPad{\PreviousTotalPages}{\the\numexpr\currentPageNumber-1\relax}.svg');%
          }%
        \fi%
      });%
      document.addEventListener('keydown',function(e){%
          \ifnum\currentPageNumber<\PreviousTotalPages
            if(e.key=='PageDown'||e.key=='ArrowDown'||e.key=='ArrowRight')%
                document.location.replace('\jobname-\zeroPad{\PreviousTotalPages}{\the\numexpr\currentPageNumber+1\relax}.svg');%
          \fi%
          \ifnum\currentPageNumber>1
            if(e.key=='PageUp'||e.key=='ArrowUp'||e.key=='ArrowLeft')%
              document.location.replace('\jobname-\zeroPad{\PreviousTotalPages}{\the\numexpr\currentPageNumber-1\relax}.svg');%
          \fi%
          if(e.key=='Home')
            document.location.replace('\jobname-\zeroPad{\PreviousTotalPages}{1}.svg');%
          if(e.key=='End')
            document.location.replace('\jobname-\PreviousTotalPages.svg');%
        });%
    ]]>%
    </script>%
    </defs>%
  }%
}%
% helper macro \zeroPad : zero-pads integer according to template,
% e. g. 123 --> 00123 if template is `99999`
% #1: arbitrary integer number as template specifying the
%     width, e. g. `987654' for a width of 6 digits
% #2: the number to be formatted
\def\zeroPad#1#2{\zeroPadI{\zeroTemplate{0}{#1}}{#2}}
%low level macros used by \zeroPad
\def\zeroPadI#1#2{% #1: string of zeros specifying width, #2 number
  \ifnum1#2<1#1
    \zeroPadI{#1}{0#2}%
  \else%
    #2%
  \fi%
}%
\def\zeroTemplate#1#2{% create template (string of zeros) from given num
  \ifnum10#1>1#2
    #1%
  \else%
    \zeroTemplate{0#1}{#2}%
  \fi%
}%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%required by PSTricks example
\usepackage[dvipsnames,svgnames]{pstricks}
\usepackage{pst-node,pst-plot,pst-eucl}
\usepackage{pst-solides3d}
\usepackage{multido}
\usepackage[nomessages]{fp}

\title{Using package \emph{animate} without Adobe}
\subtitle{Use a Web browser and press \framebox{F11}}
\author{AlexG}
\date{\today}

\begin{document}

\frame{\titlepage}

\begin{frame}{Animation}
  trivial example
  \begin{center}
    \begin{animateinline}[controls]{2}
      \multiframe{10}{i=0+1}{\Huge\fbox{\i}}
    \end{animateinline}
  \end{center}
\end{frame}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%  PSTricks example by J. Gilg
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\def\R{4}            % Radius des festen Kreises (Length fixed Circle)
\def\r{1}            % Radius des abrollenden Kreises (Length rolling Circle)
\def\A{0.75}         % Abstand erzeugenden Punkt zu Mittelpunkt des abrollenden Kreises (Length Pointer)
\def\winkel{360}     % Winkel: 1 Umlauf entspricht 360 (Angle: 1 revolution corresponds to 360)
\FPdiv{\myDeltaA}{\winkel}{90}%

\def\psBall{\rput(0,0){\psSolid[
  object=sphere,r=0.35,
  hue=0 1,
  RotX=\ai\space,ngrid=12](0,0,0)}}

\def\myFigure{%
  \pstVerb{% erzeugender Punkt (parameterized Hypocycloide)
    /Xcoord \ai\space cos \R\space \r\space sub mul \ai\space \R\space \r\space sub \r\space div mul cos \A\space mul add def % (R-r)cos(a)+A cos[(R/r-1) a]
    /Ycoord \ai\space sin \R\space \r\space sub mul \ai\space \R\space \r\space sub \r\space div mul sin \A\space mul sub def % (R-r)sin(a)-A sin[(R/r-1) a]
  }%

  % erzeugender Punkt (generating point)
  \rput(0,0){\rput(!Xcoord Ycoord){\psBall}}%

  \rput(0,0){\psSolid[object=cube,ngrid=4,
     hue=0 1,
     hollow,
     a=0.5,
     RotZ=-\ai\space](0,0,0)%
  }
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{frame}[t]{PSTricks Animation}
At the end of a rainbow \dots, by Jürgen Gilg.
\begin{itemize}
  \item best viewed in Blink-based browsers, such as Chromium, Chrome, Opera
  \item frame rate printed to JavaScript console (Ctrl+Shift+I)
\end{itemize}
\begin{center}
  \raisebox{0pt}[0.65\height][0pt]{%
  \pstVerb{/clip {} def}% disable `clip' for much better SVG performance in Firefox
  \begin{animateinline}[measure,loop,controls,height=0.8\textheight]{30}
  \multiframe{90}{i=0+1}{%
    \FPeval{ai}{myDeltaA*\i}%
    \begin{pspicture}(-5,-5)(5,5)\myFigure\end{pspicture}%
  }%
  \end{animateinline}%
}
\end{center}
\end{frame}

\begin{frame}
  \begin{center}\Huge The End\end{center}
\end{frame}

\end{document}

2 Animated SVG as file attachment to PDF

animate can export to standalone SVG animations, as outlined in https://tex.stackexchange.com/a/136919 . The SVG can be embedded as a file attachment to the PDF, and be run in a Web browser on click or touch:

\usepackage{attachfile} % or attachfile2
...
\textattachfile{animatedImage.svg}{Click!}

or without being attached:

\usepackage{hyperref}
...
\href{run:animatedImage.svg}{Click!}

In either case, the operating system/window manager must be configured to use a Web browser as default application for opening SVG files.

Chromium-based Web browsers (e. g. Chrome, Opera) should be used for viewing animated SVG, because of their extremely good rendering performance. The Lorenz attractor may serve as a test example.

3 As for PDF, ...


... there is very good news! Open-Source PDF viewers are catching up.

Okular from KDE now supports JavaScript-driven animations. See:

https://community.kde.org/GSoC/2019/StatusReports/Jo%C3%A3oNetto

Tested with Okular-1.10 (KDE-20.04.1)


We need an opensource PDF viewer with an opensource JavaScript engine added. All ingredients are there, e.g. Evince, Okular, JavaScriptCore from webkit.org (used by Apples web browser Safari), V8 (Google Chrome) or SpiderMonkey (Firefox).

MuPDF is a good starting point, but its integrated JavaScript support is quite rudimentary.

And the PDF rendering performance should be high, which is crucial for animations. MuPDF is one rendering library. The other two, Okular, Evince are based on the Poppler library.

The faster one, either MuPDF or Poppler should be chosen.

Someone should take up the challenge and put everything together.

19
  • Thanks for the answer. I'll have a look into whether it's possible to implement one of those on their devices :)
    – Platehead
    Commented Mar 27, 2015 at 12:41
  • 2
    To be clear, you are saying, "there is not yet a PDF viewer, other than Adobe, that can correctly display LaTeX animations." Is this correct? Commented Nov 2, 2015 at 18:51
  • 1
    @stvn66: Seem to work as well: PDF-XChange, Foxit (all of them closed source though). You may need to try first all three package options method=icon | widget | ocg.
    – AlexG
    Commented Nov 3, 2015 at 8:05
  • 0@stvn66 Animations most certainly don't worki in Okular, Evince or Chrome browser's integrated PDF viewer. I will give Foxit reader a go since it also has a Linux version which I can hopefully install on my Debian Jessie. Commented Mar 22, 2016 at 7:09
  • 1
    Interesting answer! I wonder why I had never seen it before! Maybe this technique could also be used for this question: tex.stackexchange.com/questions/455709/… Commented Dec 21, 2018 at 12:16

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .