diff options
Diffstat (limited to 'graphics/pgf/base/doc/pgfmanual-en-pgfsys-animations.tex')
-rw-r--r-- | graphics/pgf/base/doc/pgfmanual-en-pgfsys-animations.tex | 1654 |
1 files changed, 1654 insertions, 0 deletions
diff --git a/graphics/pgf/base/doc/pgfmanual-en-pgfsys-animations.tex b/graphics/pgf/base/doc/pgfmanual-en-pgfsys-animations.tex new file mode 100644 index 0000000000..8cab346cf1 --- /dev/null +++ b/graphics/pgf/base/doc/pgfmanual-en-pgfsys-animations.tex @@ -0,0 +1,1654 @@ +% Copyright 2019 by Till Tantau +% +% This file may be distributed and/or modified +% +% 1. under the LaTeX Project Public License and/or +% 2. under the GNU Free Documentation License. +% +% See the file doc/generic/pgf/licenses/LICENSE for more details. + + +\section{Animation System Layer} +\label{section-pgfsys-anim} + +\begin{codeexample}[setup code,hidden] +\makeatletter + +\def\animationexample#1#2#3{% + \tikz[fill=blue!25, draw=blue, ultra thick] { + \pgfidrefnextuse{\objid}{#1} + \pgfsysanimkeywhom{\objid}{#2} + \pgfidrefnextuse{\nodeid}{node} + \pgfsysanimkeyevent{\nodeid}{}{click}{}{begin} + #3 + \node [font=\footnotesize, circle, fill, draw, align=center] + (node) {Click \\ here}; + }% +} +\end{codeexample} + +In conjunction with the right output format (namely \textsc{svg}), you can +specify that certain parts of you graphics can be animated. For this, there are +a number of commands that cover, currently, what \textsc{svg 1.1} can do +regarding animations. For a detailed introduction to animations, please see +Section~\ref{section-base-animations}; the current section assumes that you are +familiar with the concepts explained there. + +The animation system consists of two layer itself: Commands starting with +|\pgfsys@anim...| and commands starting with |\pgfsysanim|. These work as +follows: +% +\begin{enumerate} + \item The commands starting with |\pgfsys@anim...| insert the actual + animation commands into the output stream. A driver must implement + these commands. + \item The command starting with |\pgfsysanim...| provide an. These + commands, which are the ones that should be called by higher layers, + implement the snapshot mechanism: When the command + |\pgfsysanimsnapshot| is used, the |\pgfsysanim...| commands do + \emph{not} call the |\pgfsys@anim...| commands but, instead, insert + non-animation commands to show the values of the attributes at the + snapshot's time. To use this abstraction layer, you have to load the + file |pgfsysanimations.code.tex|, which is not loaded by default (but + is loaded by the \pgfname\ module |animations|). +\end{enumerate} + +The bottom line is that if you wish to implement a new driver, you need to +implement the |\pgfsys@anim...| commands, if you use the animation layer, you +call the |\pgfsysanim...| commands. + + +\subsection{Animations and Snapshots} + +To add an animation to a graphic, use the following command (as described +above, the first command is the one you actually call, the second is the one a +driver implements): + +\begin{command}{\pgfsysanimate\marg{attribute}} +\end{command} + +\begin{command}{\pgfsys@animate\marg{attribute}} + The system layer animation subsystem follows the following philosophy: An + animation always concerns an \emph{attribute} of a \emph{graphic object}. A + \emph{timeline} specifies how the attribute changes its value over time. + Finally, a set of \emph{keys} configures the animation as a whole like + whether the timeline repeats or a event that triggers the start of the + animation. The four parts of an animation, namely the \emph{attribute}, the + \emph{graphic object}, the \emph{timeline}, and the \emph{keys}, are + specified in different ways: + % + \begin{enumerate} + \item You choose the \emph{attribute} using the system layer command + |\pgfsysanimate|. + \item The \emph{graphic object} whose attribute is to be animated is + \emph{always} specified by naming the ID of the graphic object + \emph{before} this object is created, see + Section~\ref{section-sys-id}. (However, in the context of + \tikzname, it suffices that the animation is given in the object's + options since these are executed before the actual object is + created). + \item The \emph{timeline} is specified using the commands + |\pgfsysanimkeytime|, which specifies a time in seconds, and + |\pgfsys@animation@val...|, which specify a value at this + particular time. The timeline specifies for a sequence of times the + values the attribute will have at these times. In between these + \emph{key times,} the value is interpolated. + \item The \emph{animation keys} are specified by commands starting + |\pgfsys@animation@...| and have the following effect: They set + some property (like, say, whether the animation repeats or whether + its effect is additive) to a given value \emph{for the current + \TeX\ scope,} but do not create any animations. Rather, when + |\pgfsysanimate| is called, a snapshot of the current values of all + animation keys is taken and added to this animation of the + attribute. + + When you set an animation key to a value, this will replace the + value previously stored for the key (all keys are empty by default + at the beginning). + + Note that animation keys are local to \TeX\ scopes, not graphics + scopes; indeed, they have little to do with the settings of the + graphics scope other than the fact that a graphic scope is also a + \TeX\ scope and thereby influence the values of these keys. + \end{enumerate} + + A typical example of how all of this works is the following: + % +\begin{codeexample}[code only] +\pgfsysanimkeyrepeatindefinite % Both of the following animations + % repeat indefinitely +{ + \pgfsysanimkeywhom{\someid}{}% The id of a later object + \pgfsysanimkeyevent{}{}{click}{0}{begin}% Begin on a click ... + \pgfsysanimkeytime{5}{1}{1}{0}{0} % Timeline starts after 5s + \pgfsysanimvalscalar{0} % With a value of 0 + \pgfsysanimkeytime{8}{1}{1}{0}{0} % Timeline ends after 8s + \pgfsysanimvalscalar{0.9} % With a value of 0.9 + \pgfsysanimate{fillopacity}% ... and the attribute is the fill opacity +} +{ + \pgfsysanimkeywhom{\someid}{}% The id of a later object + \pgfsysanimkeyoffset{0}{begin}% Begin right away ... + \pgfsysanimkeytime{1}{1}{1}{0}{0} % Timeline starts after 1s + \pgfsysanimvalcurrent % With the current value + \pgfsysanimkeytime{5}{1}{1}{0}{0} % Timeline ends after 5s + \pgfsysanimvaldimension{5pt} % With a value of 5pt + \pgfsysanimate{linewidth}% ... and the attribute is the line width +} +\end{codeexample} + % + As a real-life example, consider the following definitions, which will be + used in many examples in the rest of this section: Both take three + parameters: The \pgfname/\tikzname\ name of a to-be animated object, a type + (relevant for objects that have subtypes or parts), and some code for + triggering the actual animation. The animation will always start when the + button is clicked. The second macro sets up things in such a way that the + animation will last two seconds, while the first leaves the timing open. + % +\begin{codeexample}[code only] +\def\animationexample#1#2#3{ + \tikz[fill=blue!25, draw=blue, ultra thick] { + \pgfidrefnextuse{\objid}{#1} + \pgfsysanimkeywhom{\objid}{#2} + \pgfidrefnextuse{\nodeid}{node} + \pgfsysanimkeyevent{\nodeid}{}{click}{}{begin} + #3 + \node [font=\scriptsize, circle, fill, draw, align=center] + (node) {Click \\ here}; + } +} +\end{codeexample} + % + Now the example, where the circle will disappear, when clicked: + % +\begin{codeexample}[ + preamble={\usetikzlibrary{animations}}, + animation list={0.5,1,1.5,2}] +\animationexample{node}{}{ + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvalscalar{1} + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvalscalar{0} + \pgfsysanimate{opacity} +} +\end{codeexample} + % +\end{command} + +The ``opposite'' of |\pgfsysanimate| is the following command: + +\begin{command}{\pgfsysanimsnapshot\marg{time}} + Use this command in a scope prior to calling any other commands documented + in this section concerning the configuration of animations. In this case, + all uses of |\pgfsysanimate| inside the \TeX\ scope no longer insert an + animation into the output file. Instead, a ``snapshot'' is inserted of what + the animation ``would like at time \meta{time}''. For instance, if an + animation inserts a movement of an object by 4cm over a time of 2s and you + take a snapshot with $\meta{time} = 2\mathrm s$, you get a picture in which + the object is moved by 1cm. + + A lot of care has been taken to make the output produced by the snapshot be + as close as possible as what the animation really would look like at time + \meta{time}, but note the following restrictions: + % + \begin{enumerate} + \item Interactive events of all kinds (like |click| or |mouseover|) + make little sense for snapshots, which are created once and for all + during the typesetting of the document. For this reason, all events + are ignored for snapshots (even sync bases, and |begin| and |end| + events, which might make some sense also in a snapshot setting). + + However, there is one command which helps you with ``simulating'' + the effect of events: + % + \begin{command}{\pgfsysanimkeysnapshotstart\marg{time offset}} + This command specifies that for the current animation the + ``moment |0s|'' of the timeline is at \meta{time offset}. Thus, + it works like |\pgfsysanimkeyoffset|, only the offset is now + solely for the snapshot timeline. It has no effect on the + actual animation. + \end{command} + % + \item The command |\pgfsysanimvalcurrent| cannot be used with snapshots + since \pgfname\ has no chance of computing the correct current + value. You always have to specify the start value explicitly. + \item The computation of time splines (entry and exit splines) and the + accumulation of values after a large number of repeats may not be + numerically stable. + \end{enumerate} + % +\begin{codeexample}[width=5cm,preamble={\usetikzlibrary{animations}}] +\foreach \t in {0.5,1,1.5,2} { + \pgfsysanimsnapshot{\t} + \tikz { + \pgfidrefnextuse{\objid}{node} + \pgfsysanimkeywhom{\objid}{} + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvalscalar{1} + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvalscalar{0} + \pgfsysanimate{opacity} + \node (node) [draw = blue, very thick, fill=blue!20, circle] {Hi}; + } +} +\end{codeexample} + % +\end{command} + +\begin{command}{\pgfsysanimsnapshotafter\marg{time}} + Works like the previous command, only the ``moment'' that \meta{time} + refers to is conceptually $\meta{time} + \epsilon$: When timeline specifies + several values for \meta{time}, this command will select the last value at + \meta{time}, while |\pgfsnapshot| will select the first value at + \meta{time}. Similarly, when a timeline ends at \meta{time}, |\pgfsnapshot| + will select the last value of the timeline while |\pgfsnapshotafter| will + not apply the animation any more. +\end{command} + + +\subsection{Commands for Animating an Attribute: Color, Opacity, Visibility, Staging} + +The commands from this and the next sections specify that some attribute should +be animated. We start with rather basic animation attributes for color, +visibility, and opacity. + +\begin{sysanimateattribute}{opacity} + Adds an animation of the opacity to the graphic object specified using + |\pgfsysanimkeywhom|. If the driver supports this, this is a bit different + from animating the fill and stroke opacities individually: Paths are + treated as transparency groups for this key. Typically, ``this is what you + want''. + + Specify values with |\pgfsysanimvalscalar|. + % +\begin{codeexample}[ + preamble={\usetikzlibrary{animations}}, + animation list={0.5,1,1.5,2}, +] +\animationexample{node}{}{ + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvalscalar{1} + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvalscalar{0} + \pgfsysanimate{opacity} +} +\end{codeexample} + % +\end{sysanimateattribute} + +\begin{sysanimateattribute}{fillopacity} + Adds an animation of only the opacity of fill operations. + + Specify values with |\pgfsysanimvalscalar|. + % +\begin{codeexample}[ + preamble={\usetikzlibrary{animations}}, + animation list={0.5,1,1.5,2}, +] +\animationexample{node}{}{ + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvalscalar{1} + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvalscalar{0} + \pgfsysanimate{fillopacity} +} +\end{codeexample} + % +\end{sysanimateattribute} + +\begin{sysanimateattribute}{strokeopacity} + Adds an animation of only the opacity of draw (stroke) operations. + + Specify values with |\pgfsysanimvalscalar|. + % +\begin{codeexample}[ + preamble={\usetikzlibrary{animations}}, + animation list={0.5,1,1.5,2}, +] +\animationexample{node}{}{ + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvalscalar{1} + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvalscalar{0} + \pgfsysanimate{strokeopacity} +} +\end{codeexample} + % +\end{sysanimateattribute} + +\begin{sysanimateattribute}{visibility} + Adds an animation of the ``visibility''. + + Specify values with |\pgfsysanimvaltext|. However, only two values are + allowed: |visible| and |hidden|. + % +\begin{codeexample}[ + preamble={\usetikzlibrary{animations}}, + animation list={-1,0,1,2,3}, +] +\animationexample{node}{}{ + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvaltext{hidden} + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvaltext{hidden} + \pgfsysanimate{visibility} +} +\end{codeexample} + % +\end{sysanimateattribute} + +\begin{sysanimateattribute}{strokecolor} + Adds an animation of the stroke color. + + Specify values with |\pgfsysanimvalcolorrgb| and friends. + % +\begin{codeexample}[ + preamble={\usetikzlibrary{animations}}, + animation list={0.5,1,1.5,2}, +] +\animationexample{node}{}{ + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvalcolorrgb{0}{0}{0} + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvalcolorrgb{1}{0}{0} + \pgfsysanimate{strokecolor} +} +\end{codeexample} + % +\end{sysanimateattribute} + +\begin{sysanimateattribute}{fillcolor} + Adds an animation of the fill color. + + Specify values with |\pgfsysanimvalcolorrgb| and friends. + % +\begin{codeexample}[ + preamble={\usetikzlibrary{animations}}, + animation list={0.5,1,1.5,2}, +] +\animationexample{node}{}{ + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvalcolorrgb{0}{0}{0} + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvalcolorrgb{1}{0}{0} + \pgfsysanimate{fillcolor} +} +\end{codeexample} + % +\end{sysanimateattribute} + + +\subsection{Commands for Animating an Attribute: Paths and Their Rendering} + +The following attributes influence paths and how they are rendered. + +\begin{sysanimateattribute}{path} + Adds an animation of the path itself. That means that the path will morph + its form from one path to another. When morphing a path, all ``values'', + which are the paths, must consist of the \emph{exact same} path + construction commands; they may only differ with respect to the numbers + used in these descriptions. + + Specify values with |\pgfsysanimvalpath|. + % +\begin{codeexample}[ + preamble={\usetikzlibrary{animations}}, + animation list={0.5,1,1.5,2}, + animation bb={(0.9,-0.1)rectangle(2.1,1.1)}, +] +\animationexample{my path}{path}{ + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvalpath{\pgfsys@moveto{1cm}{0cm}% + \pgfsys@lineto{1cm}{1cm}% + \pgfsys@lineto{2cm}{0cm}} + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvalpath{\pgfsys@moveto{1cm}{1cm}% + \pgfsys@lineto{2cm}{1cm}% + \pgfsys@lineto{1cm}{0cm}} + \pgfsysanimate{path} + \filldraw [ultra thick,draw=blue,fill=blue!20, name=my path] + (1,0) -- (1,1) -- (2,0); } +\end{codeexample} + + You can attach arrow tips to paths that are animated and these arrow tips + will correctly ``rotate and move along'' with the path's end points + \emph{if} you take the following points into considerations: + % + \begin{itemize} + \item Arrow tips that ``rotate and move along'' with a path must be + specified using a special animation command, see below. The normal + arrow tips added to a path would \emph{not} be animated + automatically and, indeed, if you add arrow tips to a path using + |\pgfsetarrows| and then animate the path, you will get an error + message. + \item Internally, the arrow tips that ``rotate and move along'' are + drawn using so-called \emph{markers}. These are little graphic + objects that can be added to the start and end of paths and that + are automatically rotated and move along with the path. + + In principle, the rendering rules used by \textsc{svg} for markers + are the same as for normal arrow tips: The markers are rotated and + moved so that the point along a tangent of the path at the start or + end of the path. However, when it comes to special cases such as a + path with multiple segments, a path with degenerate segments, a + closed path, and so on, the rules used by for instance \textsc{svg} + may differ from the placement that \pgfname\ will compute. + + Thus, it is best to add arrow tips only to ``normal'' paths + consisting of a single open path segment whose ends can be + shortened a bit without causing degeneration. + \item When an arrow tip is added to a path, the path must typically be + shortened a bit so that the \emph{tip} of the arrow ends where the + path would usually end. This shortening is not done by the system + layer for to-be-animated paths; you must compute and then animate + these shortened paths yourself. (However, the basic layer animation + module will do this for you, so you only have to worry about this + when you use the system layer directly.) + \end{itemize} + + Let us now have a look at how we add arrow tip markers: + % + \begin{command}{\pgfsysanimkeytipmarkers\marg{start marker}\marg{end marker}} + \end{command} + % + \begin{command}{\pgfsys@animation@tip@markers\marg{start marker}\marg{end marker}} + This command specifies that during a path animation the two markers + provided as parameters should be added (and rotated and moved along + with the path) at the start and end. The \meta{start marker} must + either be empty (in which case no marker is added at the start) or it + must be a macro storing a value returned by the command + |\pgfsys@marker@declare|. In this case, the marker declared symbol will + be added to the start during the animation. The same situation applies + to the end of the path. + + As pointed out earlier, only arrow tips / markers added to paths using + this command will be animated along with the path. In particular, you + should \emph{not} add arrow tips to to-be-animated paths using + |\pgfsetarrow|. However, when you use a base value + (|\pgfsys@animation@base|) to set a path, the arrow tips will also be + added to this base path. + + To sum up, the ``correct'' way of adding arrow tips to a path that is + animated is to proceed as follows: + % + \begin{enumerate} + \item You specify arrow tips for a path using this command. + \item You specify times and values of the to-be-animated path, + shortened as necessary to accommodate the length of the arrow + tips. + \item You specify the first (or, possibly, some other) value in the + time--value sequence as a base value. + \item You create a path animation that applies to a future path. + \item You create this future path as an empty path without arrow + tips and draw it. Because of the setting of the base value, + instead of the empty path the base path will be used as the + ``real'' path and the animation's arrow tips will be added as + arrow tips. + \end{enumerate} + + When you have more than one animation for a given path, these different + animations may use different arrow tips / markers. This allows you to + animate (change) which arrow tip is used on a path over time. + % +\begin{codeexample}[ + preamble={\usetikzlibrary{animations}}, + animation list={0.5,1,1.5,2}, + animation bb={(0.7,-0.3)rectangle(2.3,1.3)}, +] +% Declare a marker: +\pgfsys@marker@declare\mymarker{% + \pgfscope% + \pgfsetcolor{red!75}% + \pgfpathmoveto{\pgfpoint{0pt}{5pt}}\pgfpathlineto{\pgfpoint{8pt}{0pt}}% + \pgfpathlineto{\pgfpoint{0pt}{0pt}}\pgfpathclose% + \pgfusepathqfill% + \endpgfscope% + \pgfpathmoveto{\pgfpoint{0pt}{5pt}}\pgfpathlineto{\pgfpoint{8pt}{0pt}}% + \pgfpathlineto{\pgfpoint{0pt}{-5pt}}\pgfpathclose% + \pgfusepathqstroke% +}% +\animationexample{my path}{path}{ + \pgfsysanimkeytipmarkers{\mymarker}{\mymarker} + \pgfsysanimkeybase + \pgfsysanimvalpath{\pgfsys@moveto{1cm}{0cm}% + \pgfsys@lineto{1cm}{1cm}% + \pgfsys@lineto{2cm}{0cm}} + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvalpath{\pgfsys@moveto{1cm}{0cm}% + \pgfsys@lineto{1cm}{1cm}% + \pgfsys@lineto{2cm}{0cm}} + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvalpath{\pgfsys@moveto{1cm}{1cm}% + \pgfsys@lineto{2cm}{1cm}% + \pgfsys@lineto{1cm}{0cm}} + \pgfsysanimate{path} + \filldraw [ultra thick,draw=blue,fill=blue!20, name=my path]; + \path (1,0) (2,1);} +\end{codeexample} + \end{command} +\end{sysanimateattribute} + +\begin{sysanimateattribute}{linewidth} + Adds an animation of the line width. + + Specify values with |\pgfsysanimvaldimension|. + % +\begin{codeexample}[ + preamble={\usetikzlibrary{animations}}, + animation list={0.5,1,1.5,2}, +] +\animationexample{node}{}{ + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvaldimension{1pt} + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvaldimension{10pt} + \pgfsysanimate{linewidth} +} +\end{codeexample} + % +\end{sysanimateattribute} + +\begin{sysanimateattribute}{dash} + Adds an animation of the dash phase and pattern (like |\pgfsys@setdash|). + + Specify values with |\pgfsysanimvaldash|. + % +\begin{codeexample}[ + preamble={\usetikzlibrary{animations}}, + animation list={0.5,1,1.5,2}, +] +\animationexample{node}{}{ + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvaldash{1pt,10pt}{0pt} + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvaldash{10pt,3pt}{0pt} + \pgfsysanimate{dash} +} +\end{codeexample} + % +\begin{codeexample}[ + preamble={\usetikzlibrary{animations}}, + animation list={0.5,1,1.5,2}, +] +\animationexample{node}{}{ + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvaldash{1cm,1pt}{0pt} + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvaldash{1cm,1pt}{1cm} + \pgfsysanimate{dash} +} +\end{codeexample} + % +\begin{codeexample}[ + preamble={\usetikzlibrary{animations}}, + animation list={0.5,1,1.5,2}, +] +\animationexample{node}{}{ + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvaldash{3pt,1pt}{0pt} + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvaldash{1pt,3pt}{10pt} + \pgfsysanimate{dash} +} +\end{codeexample} + % +\end{sysanimateattribute} + + +\subsection{Commands for Animating an Attribute: Transformations and Views} + +The commands in this section allow you to animate the canvas transformation +matrix of a scope. However, there is one command that needs to be explained +first. + +\begin{command}{\pgfsysanimkeycanvastransform\marg{pre}\marg{post}} +\end{command} +% +\begin{command}{\pgfsys@animation@canvas@transform\marg{pre}\marg{post}} + In order to animate the canvas, you specify that, for instance, the canvas + should be shifted over, say, one second by 2cm from left to right. In order + to specify this, you specify that an additional shift should be added to + the canvas transformation matrix that starts out as $(0,0)$ and ends at + $(2\,\mathrm{cm},0)$. However, it is not immediately clear what ``to the + right'' or $(2\,\mathrm{cm},0)$ actually means: ``Right'' relative to the + paper? ``Right'' relative to the coordinate system at the point when the + animation is created? ``Right'' relative to the object's local coordinate + system? + + Using this command you can specify the coordinate system relative to which + all canvas animations are specified. In detail, when you add an animation + $a$ of the canvas of an object foo, the following happens: + % + \begin{enumerate} + \item We start with the canvas transformation matrix that is installed + when the object starts. More precisely, this is the canvas + transformation matrix that is in force when the command + |\pgfsys@begin@idscope| is called for the object. The canvas + transformation matrix that is in force when the animation is + created (which is typically ``way before'' the object is created + and may even be in a totally different graphics scope) is + irrelevant for the animation. + \item Now, when the object is created, the code \meta{pre} is executed. + It should call |\pgfsys@transformcm| at most once. This canvas + transformation is added to the object's canvas transformation. + \item Now, the animation $a$ of the canvas is relative to the resulting + canvas transformation. That means, when the animation shifts the + object ``to the right'' the animation will actually be along the + current direction of ``right'' in the canvas transformation + resulting from the two transformations above. + \item Finally, at the point of creation of the to-be-animation object + the code \meta{post} is executed. Again, the code should call + |\pgfsys@transformcm| at most once. The resulting transformation is + also added to the object's canvas transformation, but does + \emph{not} influence the animation. + \end{enumerate} + + The net effect of the above is that, normally, you use the \meta{pre} code + to setup a transformation matrix relative to which you wish to perform your + animation and, normally, you use \meta{post} to undo this transformation + (using the inverted matrix) to ensure that when no animation is in force, + the object is placed at the same position as if no animation were used. + + Let us now have a look at some examples. We use the following macro, which + takes a pre and a post code and animates a red ball over 1cm to the right + in two seconds and rotates the blue ball over 90$^\circ$ around the origin. + The ball is placed at $(1,0)$. + % +\begin{codeexample}[code only,setup code] +\def\animationcanvasexample#1#2{% + \animationexample{ball}{}{% + \pgfsysanimkeycanvastransform{#1}{#2}% + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvaltranslate{0cm}{0cm}% + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvaltranslate{1cm}{0cm}% + \pgfsysanimate{translate} + \fill [ball color=red,name=ball] (1,0) circle [radius=3mm]; } + \animationexample{ball}{}{% + \pgfsysanimkeycanvastransform{#1}{#2}% + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvalscalar{0}% + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvalscalar{90}% + \pgfsysanimate{rotate} + \fill [ball color=blue,name=ball] (1,0) circle [radius=3mm]; } } +\end{codeexample} + % +% TODOsp: codeexamples: this definition is needed for the next 4 `codeexample`s +% but because of the hash sign it can't simply be added `pre` +\def\animationcanvasexample#1#2{% + \animationexample{ball}{}{% + \pgfsysanimkeycanvastransform{#1}{#2}% + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvaltranslate{0cm}{0cm}% + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvaltranslate{1cm}{0cm}% + \pgfsysanimate{translate} + \fill [ball color=red,name=ball] (1,0) circle [radius=3mm]; } + \animationexample{ball}{}{% + \pgfsysanimkeycanvastransform{#1}{#2}% + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvalscalar{0}% + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvalscalar{90}% + \pgfsysanimate{rotate} + \fill [ball color=blue,name=ball] (1,0) circle [radius=3mm]; } } + +\begin{codeexample}[ + width=9.9cm, + preamble={\usetikzlibrary{animations}}, + animation list={0.5,1,1.5,2}, +] +\animationcanvasexample +{} +{} +\end{codeexample} + % +\begin{codeexample}[ + width=9.9cm, + preamble={\usetikzlibrary{animations}}, + animation list={0.5,1,1.5,2}, +] +\animationcanvasexample +{\pgfsys@transformshift{10mm}{0mm}} +{\pgfsys@transformshift{-10mm}{0mm}} +\end{codeexample} + % +\begin{codeexample}[ + width=9.9cm, + preamble={\usetikzlibrary{animations}}, + animation list={0.5,1,1.5,2}, +] +\animationcanvasexample +{\pgfsys@transformcm{0.5}{0.5}{-0.5}{0.5} + {0pt}{0pt}} +{} +\end{codeexample} + % +\begin{codeexample}[ + width=9.9cm, + preamble={\usetikzlibrary{animations}}, + animation list={0.5,1,1.5,2}, +] +\animationcanvasexample +{\pgfsys@transformcm{0.5}{0.5}{-0.5}{0.5} + {0pt}{0pt}} +{\pgfsys@transformcm{1}{-1}{1}{1} + {0pt}{0pt}} +\end{codeexample} + % +\end{command} + +\begin{sysanimateattribute}{translate} + Adds an (additional) translate animation. Effectively, this causes the + group to be shifted to different positions. + + Specify values with |\pgfsysanimvaltranslate|. + % +\begin{codeexample}[ + preamble={\usetikzlibrary{animations}}, + animation list={0.5,1,1.5,2}, +] +\animationexample{node}{}{ + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvaltranslate{0cm}{0cm}% + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvaltranslate{5mm}{-1cm} + \pgfsysanimate{translate} +} +\end{codeexample} + % +\end{sysanimateattribute} + +\begin{sysanimateattribute}{scale} + Adds an animation of the scaling relative to the origin. This causes a + scaling of the canvas, including fonts and line widths. + + Specify values with |\pgfsysanimvalscale|. + % +\begin{codeexample}[ + preamble={\usetikzlibrary{animations}}, + animation list={0.5,1,1.5,2}, +] +\animationexample{node}{}{ + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvalscale{1}{1}% + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvalscale{0.5}{2} + \pgfsysanimate{scale} +} +\end{codeexample} + % +\end{sysanimateattribute} + +\begin{sysanimateattribute}{rotate} + Adds a rotation animation around the origin. + + Specify values with |\pgfsysanimvalscalar|. + % +\begin{codeexample}[ + preamble={\usetikzlibrary{animations}}, + animation list={0.5,1,1.5,2}, + ] +\animationexample{node}{}{ + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvalscalar{0}% + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvalscalar{90} + \pgfsysanimate{rotate} +} +\end{codeexample} + % +\end{sysanimateattribute} + +\begin{sysanimateattribute}{skewx} + Adds an animation of a skewing of the canvas along the $x$-axis. Unlike the + |slant| options of \tikzname, the skew is given in degrees. + + Specify values with |\pgfsysanimvalscalar|. + % +\begin{codeexample}[ + preamble={\usetikzlibrary{animations}}, + animation list={0.5,1,1.5,2}, +] +\animationexample{node}{}{ + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvalscalar{0}% + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvalscalar{45} + \pgfsysanimate{skewx} +} +\end{codeexample} + % +\end{sysanimateattribute} + +\begin{sysanimateattribute}{skewy} + Adds an animation of a skewing of the canvas along the $y$-axis. + + Specify values with |\pgfsysanimvalscalar|. +\end{sysanimateattribute} + +\begin{sysanimateattribute}{motion} + Works a bit like |\pgfsysanimvaltranslate|: It also adds an animated shift + transformation of the canvas. However, instead of specifying some shift + coordinates as values, you now specify a whole path (which may include + curves). The effect is that an animated translate transformation for the + different points on this path gets installed. Furthermore, if you use + |\pgfsysanimkeyrotatealong|, an additional adaptive rotation transformation + will be added so that the animated graphic scope ``points along'' the path. + + You specify the path along which you wish to move objects along using + |\pgfsysanimkeymovealong|. You use the timeline to specify how far the + object gets moved along this path using scalar values where |0| is the + beginning of the path and |1| is the end. Thus, setting the timeline to the + scalar value of |0| at time $t_0$ and to |1| at time $t_1$ will cause the + object o move along the complete path between times $t_0$ and $t_1$. + + Specify values with |\pgfsysanimvalscalar|. + + \begin{command}{\pgfsysanimkeymovealong\marg{path}} + \end{command} + % + \begin{command}{\pgfsys@animation@movealong\marg{path}} + Defines the \meta{path} along which the motion will occur. It will + simply be executed and must call |\pgfsys@lineto| and similar + path-construction commands, but should not call other commands. + % +\begin{codeexample}[ + preamble={\usetikzlibrary{animations}}, + animation list={0.5,1,1.5,2}, + render instead={ +\animationexample{node}{}{ + \pgfsysanimkeymovealong{ + \pgfsyssoftpath@movetotoken{0pt}{0pt} + \pgfsyssoftpath@linetotoken{0pt}{-5mm} + \pgfsyssoftpath@curvetosupportatoken{0pt}{-1cm}% + \pgfsyssoftpath@curvetosupportbtoken{0pt}{-1cm}% + \pgfsyssoftpath@curvetotoken{-5mm}{-1cm} } + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvalscalar{0} + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvalscalar{1} + \pgfsysanimate{motion} +} + }] +\animationexample{node}{}{ + \pgfsysanimkeymovealong{ + \pgfsyssoftpath@movetotoken{0pt}{0pt} + \pgfsyssoftpath@linetotoken{0pt}{-5mm} + \pgfsyssoftpath@curvetosupportatoken{0pt}{-1cm}% + \pgfsyssoftpath@curvetosupportbtoken{0pt}{-1cm}% + \pgfsyssoftpath@curvetotoken{-5mm}{-1cm} } + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvalscalar{0} + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvalscalar{1} + \pgfsysanimate{motion} +} +\end{codeexample} + \end{command} + + \begin{command}{\pgfsysanimkeynorotatealong} + \end{command} + % + \begin{command}{\pgfsys@animation@norotatealong} + Indicates that no additional rotation should be added during the + movement. This is the default. + \end{command} + + \begin{command}{\pgfsysanimkeyrotatealong} + \end{command} + % + \begin{command}{\pgfsys@animation@rotatealong} + Indicates that the to-be-animated group should be rotated automatically + so that it points along the path as time progresses. This option is + only applicable to motion animations. + % +\begin{codeexample}[ + preamble={\usetikzlibrary{animations}}, + animation list={0.5,1,1.5,2}, + render instead={ +\animationexample{node}{}{ + \pgfsysanimkeyrotatealong + \pgfsysanimkeymovealong{ + \pgfsyssoftpath@movetotoken{0pt}{0pt} + \pgfsyssoftpath@linetotoken{0pt}{-5mm} + \pgfsyssoftpath@curvetosupportatoken{0pt}{-1cm}% + \pgfsyssoftpath@curvetosupportbtoken{0pt}{-1cm}% + \pgfsyssoftpath@curvetotoken{-5mm}{-1cm} } + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvalscalar{0} + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvalscalar{1} + \pgfsysanimate{motion} +}}] +\animationexample{node}{}{ + \pgfsysanimkeyrotatealong + \pgfsysanimkeymovealong{% + \pgfsyssoftpath@movetotoken{0pt}{0pt}% + \pgfsyssoftpath@linetotoken{0pt}{-5mm}% + \pgfsyssoftpath@curvetosupportatoken{0pt}{-1cm}% + \pgfsyssoftpath@curvetosupportbtoken{0pt}{-1cm}% + \pgfsyssoftpath@curvetotoken{-5mm}{-1cm}} + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvalscalar{0}% + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvalscalar{1} + \pgfsysanimate{motion} +} +\end{codeexample} + \end{command} +\end{sysanimateattribute} + +\begin{sysanimateattribute}{viewbox} + Adds an animation of the view box. The graphic scope to which this + animation is added must have been created using |\pgfsys@viewboxmeet| or + |\pgfsys@viewboxslice|; adding it to other scopes has no effect. Note that + this command does \emph{not} change or animate the scope's transformation + matrix -- it only animates the ``what we see through the view box''. + + Specify values with |\pgfsysanimvalviewbox|. + % +\begin{codeexample}[ + width=5cm, + preamble={\usetikzlibrary{animations,views}}, + animation list={0.5,1,1.5,2}, + animation bb={(0.9,-2.1) rectangle (3.1,2.1)}, +] +\animationexample{my view}{view}{ + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvalviewbox{-10mm}{-20mm}{10mm}{20mm}% + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvalviewbox{15mm}{-15mm}{27mm}{8mm}% + \pgfsysanimate{viewbox} + \scoped [xshift=2cm] { + \draw [red] (-1,-2) rectangle (1,2) node [font=\scriptsize, + below left, align=right] {original\\ view\\ box}; + \scoped [meet={(-1,-2) (1,2)}, name=my view] { + \draw (-5mm,-15mm) rectangle (7mm,8mm) + node [font=\scriptsize, align=right, below left] + {target\\ view\\ box}; + \filldraw (0,0) circle [radius=3mm]; +} } } +\end{codeexample} + % +\end{sysanimateattribute} + + +\subsection{Commands for Specifying the Target Object} + +\begin{command}{\pgfsysanimkeywhom\marg{id}\marg{type}} +\end{command} +% +\begin{command}{\pgfsys@animation@whom\marg{id}\marg{type}} + Sets the target of the animation. The \marg{id} must previously have been + created using |\pgfsys@new@id|, \marg{type} must be a type (the empty type + is also allowed). See Section~\ref{section-sys-id} for details on ids and + types. +\end{command} + + +\subsection{Commands for Specifying Timelines: Specifying Times} + +Animations are specified using \emph{timelines}, which are functions mapping +times to values for these times. The functions are cubic splines, which are +specified using time--value pairs plus control points. + +In order to specify a time--value pair, you first use the command +|\pgfsysanimkeytime| to specify a time. Next, you use |\pgfsysanimval...| to +specify a value, which adds the time--value pair to the timeline. Note that the +times must be given in non-decreasing order. Between time--value pairs, the +values are interpolated using a spline. + +The first and last times of the timeline are a bit special: The timeline starts +on the first time and the duration of the timeline is the difference between +the first and last time. ``Starting'' on the start time actually means that any +beginnings (see the commands for specifying beginnings and endings) get as +offset the start time; similarly end times are offset by this value. + +\begin{command}{\pgfsysanimkeytime\marg{time}\marg{entry spline + control x}\marg{entry spline control y}\marg{exit spline + control x}\marg{exit spline control y}% +} +\end{command} +\begin{command}{\pgfsys@animation@time\marg{time}\marg{entry spline + control x}\marg{entry spline control y}\marg{exit spline + control x}\marg{exit spline control y}% +} + The \meta{time} is a number representing seconds (so |0.5| means 500\,ms). + + The spline between a time--value pair and the next is specified using the + four parameters following the time. The first two of these specify the + second control point of the interval preceding the time--value pair (called + the ``entry'' control point), the last two parameters specify the first + control point of the interval following the pair (called the ``exit'' + control point). Consider for instance, the following calls: + % +\begin{codeexample}[code only] +\pgfsysanimkeytime{10}{0.1}{0.2}{0.3}{0.4} +\pgfsysanimvalscalar{100} +\pgfsysanimkeytime{15}{0.5}{0.6}{0.7}{0.8} +\pgfsysanimvalscalar{200} +\end{codeexample} + % + This will create (at least) the time interval $[10\,\mathrm s,15\,\mathrm + s]$ and the control points for this interval will be $(0.3,0.4)$ and + $(0.5,0.6)$. + + Control points are specified in a different ``coordinate'' system from the + time--value pairs themselves: While the time--value pairs are specified + using a number representing seconds and a value using some special + commands, the control points are specified as numbers between $0$ and $1$, + each time representing a fraction of the time interval or the value + interval. In the example, the time interval is $[10\,\mathrm s,15\,\mathrm + s]$ and the value interval is $[100,200]$. This means that a control point + of $(0.3,0.4)$ actually refers to the time--value $(11.5\,\mathrm s,140)$. + The ``time--value curve'' in the interval thus ``\texttt{(10s,100) .. + controls (11.5s,140) and (12.5s,160) .. (15s,200)}''. + + Note that by setting the control points always to $(1,1)$ and $(0,0)$ you + get a linear interpolation between time--value pairs. + + Two special cases are the following: When the two last parameters, the exit + spline, take the special values |stay| and |0|, the attribute's value + ``stays'' until the next value for the next time (it then ``jumps'' to the + next value then). This corresponds, roughly, to an ``infinite'' \meta{exit + spline control x}. Similarly, when the entry spline parameters take the + special values |jump| and |1|, the value immediately jumps from the + previous value to the next value when the previous value was specified. +\end{command} + +\begin{command}{\pgfsysanimkeybase} +\end{command} +% +\begin{command}{\pgfsys@animation@base} + This command can be used in any place where |\pgfsys@animation@time| is + usually used. The effect is that the next value does not become part of the + timeline, but will become the value used for the attribute when no + animation is active. (Normally, when the animation is not active, no value + is set at all and the value is inherited from the surrounding scope.) +\end{command} + +It may happen that there is more than one timeline active that is ``trying to +modify'' a given attribute. In this case, the following rules are used to +determine, which timeline ``wins'': +% +\begin{enumerate} + \item If no animation is active at the current time (all animation either + have not yet started or they have already ended), then the base value + given in the animation encountered last in the code is used. (If there + are no base values, the attribute is taken from the surrounding scope.) + \item If there are several active animations, the one that has started last + is used and the its value is used. + \item If there are several active animations that have started at the same + time, the one that comes last in the code is used. +\end{enumerate} + +Note that these rules do not apply to transformations of the canvas since these +are always additive (or, phrased differently, they are always all active and +the effects accumulate). + + +\subsection{Commands for Specifying Timelines: Specifying Values} + +The following commands are used to specify the values of a timeline. Each use +of one of the following commands adds one time--value pair to the timeline. +Which of the commands must be used depends on the type of the to-be-animated +attribute (see the |\pgfsysanimate| command instances, which list the command +that must be used). + +\begin{command}{\pgfsysanimvalcurrent} +\end{command} +\begin{command}{\pgfsys@animation@val@current} + Creates a time--value pairs where the value is the current value that the + attribute has. This command can only be used in conjunction with ``real'' + animations, when you use it with a snapshot an error is raised. +\end{command} + +\begin{command}{\pgfsysanimvaltext\marg{text}} +\end{command} +\begin{command}{\pgfsys@animation@val@text\marg{text}} + Creates a time--value pairs where the value is some text. Which texts are + permissible depends on the to-be-animated attribute. +\end{command} + +\begin{command}{\pgfsysanimvalscalar\marg{number}} +\end{command} +\begin{command}{\pgfsys@animation@val@scalar\marg{number}} + Creates a time--value pairs where the value is a number like |0.5| or + |-2.25|. +\end{command} + +\begin{command}{\pgfsysanimvaldimension\marg{dimension}} +\end{command} +\begin{command}{\pgfsys@animation@val@dimension\marg{dimension}} + Creates a time--value pairs where the value is a \TeX\ dimension like + |0.5pt| or |-2in|. +\end{command} + +\begin{command}{\pgfsysanimvalcolorrgb\marg{red}\marg{green}\marg{blue}} +\end{command} +\begin{command}{\pgfsys@animation@val@color@rgb\marg{red}\marg{green}\marg{blue}} + Creates a time--value pairs where the value is color specified by three + fractional values between 0 and 1 for the red, the green, and the blue + part. +\end{command} + +\begin{command}{\pgfsysanimvalcolorcmyk\marg{cyan}\marg{magenta}\marg{yellow}\marg{black}} +\end{command} +\begin{command}{\pgfsys@animation@val@color@cmyk\marg{cyan}\marg{magenta}\marg{yellow}\marg{black}} + Creates a time--value pairs where the value is color specified by four + fractional values between 0 and 1 for the cyan, magenta, yellow, and black + part. +\end{command} + +\begin{command}{\pgfsysanimvalcolorcmy\marg{cyan}\marg{magenta}\marg{yellow}} +\end{command} +\begin{command}{\pgfsys@animation@val@color@cmy\marg{cyan}\marg{magenta}\marg{yellow}} + Like the |\pgfsysanimvalcolorcmyk| only without the black part. +\end{command} + +\begin{command}{\pgfsysanimvalcolorgray\marg{gray value}} +\end{command} +\begin{command}{\pgfsys@animation@val@color@gray\marg{gray value}} + Creates a time--value pairs where the value is gray value (a + fraction between 0 and 1). +\end{command} + +\begin{command}{\pgfsysanimvalpath\marg{low-level path construction commands}} +\end{command} +\begin{command}{\pgfsys@animation@val@path\marg{low-level path construction command}} + Creates a time--value pairs where the value is path. The \meta{low-level + commands} must consist of a sequence of path construction commands like + |\pgfsys@lineto| or |\pgfsyssoftpath@linetotoken| (more precisely, the + commands must form a list of \TeX\ tokens and dimensions surrounded by + braces). For each call of this command, the sequence of tokens and numbers + must be the some. During the animation, only and exactly the numbers will + be interpolated. +\end{command} + +\begin{command}{\pgfsysanimvaltranslate\marg{x dimension}\marg{y dimension}} +\end{command} +\begin{command}{\pgfsys@animation@val@translate\marg{x dimension}\marg{y dimension}} + Creates a time--value pairs where the value is a coordinate. The dimensions + must be \TeX\ dimensions. +\end{command} + +\begin{command}{\pgfsysanimvalscale\marg{x scale}\marg{y scale}} +\end{command} +\begin{command}{\pgfsys@animation@val@scale\marg{x scale}\marg{y scale}} + Creates a time--value pairs where the value is pair of scalar values. +\end{command} + +\begin{command}{\pgfsysanimvalviewbox\marg{$x_1$}\marg{$y_1$}\marg{$x_2$}\marg{$y_2$}} +\end{command} +\begin{command}{\pgfsys@animation@val@viewbox\marg{$x_1$}\marg{$y_1$}\marg{$x_2$}\marg{$y_2$}} + Creates a time--value pairs where the value is view box. The lower left + corner is given by $(x_1,y_1)$, consisting of two \TeX\ dimensions, and the + upper right corner is $(x_2,y_2)$. +\end{command} + +\begin{command}{\pgfsysanimvaldash\marg{pattern}\marg{phase}} +\end{command} +\begin{command}{\pgfsys@animation@val@dash\marg{pattern}\marg{phase}} + Creates a time--value pairs where the value is dash pattern and phase with + the same syntax as |\pgfsys@setdash|. +\end{command} + + +\subsection{Commands for Specifying Timing: Repeats} + +\begin{command}{\pgfsysanimkeyrepeat{number of times}} +\end{command} +\begin{command}{\pgfsys@animation@repeat\marg{number of times}} + Specifies that the animation should repeat the specified \meta{number of + times}, which may be a fractional number. + % +\begin{codeexample}[ + width=6cm, + preamble={\usetikzlibrary{animations}}, + animation list={1,2,3,4,5,6,7,8}, +] +\animationexample{node}{}{ + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvaltranslate{0cm}{0cm} + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvaltranslate{0cm}{-1cm} + \pgfsysanimkeyrepeat{2.5} + \pgfsysanimate{translate} } +\end{codeexample} + % +\end{command} + +\begin{command}{\pgfsysanimkeyrepeatindefinite} +\end{command} +\begin{command}{\pgfsys@animation@repeat@indefinite} + Specifies that the animation should repeat indefinitely. + % +\begin{codeexample}[ + width=6cm, + preamble={\usetikzlibrary{animations}}, + animation list={1,2,3,4,5,6,7,8}, +] +\animationexample{node}{}{ + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvaltranslate{0cm}{0cm} + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvaltranslate{0cm}{-1cm} + \pgfsysanimkeyrepeatindefinite + \pgfsysanimate{translate} } +\end{codeexample} + % +\end{command} + +\begin{command}{\pgfsysanimkeyrepeatdur\meta{seconds}} +\end{command} +\begin{command}{\pgfsys@animation@repeat@dur\meta{seconds}} + Specifies that the animation should repeat until \meta{seconds} have + elapsed. + % +\begin{codeexample}[ + width=6cm, + preamble={\usetikzlibrary{animations}}, + animation list={1,2,3,4,5,6,7,8}, +] +\animationexample{node}{}{ + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvaltranslate{0cm}{0cm} + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvaltranslate{0cm}{-1cm} + \pgfsysanimkeyrepeatdur{5} + \pgfsysanimate{translate} } +\end{codeexample} + % +\end{command} + + +\subsection{Commands for Specifying Timing: Beginning and Ending} + +Normally, animations start when a graphic is displayed. Using the following +commands, you can change this behavior: For instance, you can specify that the +animation should start when, say, some button has been pressed or a key has +been hit. Similarly, you can also use the commands to specify that the +animation should stop early, for instance when a button is pressed. + +Note that all of the commands for specifying a nonstandard begin (or end) of an +animation's timeline refer to when the time $0\,\mathrm s$ of the timeline +should actually be. If the first time--value point for a timeline is at, say, +2\,s and you specify that the begin of the animation is one second after the +click of a button, the attribute will attain the value specified by the +time--value point three seconds after the button has been pressed. + +All of the following commands take either the text |begin| or |end| as their +last argument. + +You can call the commands several times. This will result in several different +possible beginnings (or endings). + +\begin{command}{\pgfsysanimkeyoffset\marg{time offset}\marg{begin or end}} +\end{command} +\begin{command}{\pgfsys@animation@offset\marg{time offset}\marg{begin or end}} + Specifies that (in addition to any other beginnings or endings) the + animation's timeline should begin (or end) \meta{time offset} many seconds + after the graphic is shown. For instance, in the next example the animation + will start automatically after 5\,s \emph{or} when then button is pressed. + % +\begin{codeexample}[ + width=6cm, + preamble={\usetikzlibrary{animations}}, + animation list={1,2,3,4,5,6,7,8}, +render instead={ +\animationexample{node}{}{ + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvaltranslate{0cm}{0cm} + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvaltranslate{0cm}{-1cm} + \pgfsysanimkeyoffset{5}{begin} + \pgfsysanimkeysnapshotstart{5} + \pgfsysanimate{translate} } + }] +\animationexample{node}{}{ + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvaltranslate{0cm}{0cm} + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvaltranslate{0cm}{-1cm} + \pgfsysanimkeyoffset{5}{begin} + \pgfsysanimate{translate} } +\end{codeexample} + % +\end{command} + +\begin{command}{\pgfsysanimkeysyncbegin\marg{sync base id}\marg{type}\marg{time offset}\marg{begin or end}} +\end{command} +\begin{command}{\pgfsys@animation@syncbegin\marg{sync base id}\marg{type}\marg{time offset}\marg{begin or end}} + Specifies that the animation should begin \meta{time offset} many seconds + after the \meta{sync base id} with the given \meta{type} has begun. Here, + the \meta{sync base id} must have been obtained using |\pgfsys@new@id|. + + The idea behind a sync base is that you setup an animation and name it, + other animations can start alongside this animation. An animation whose + sole purpose is to orchestrate other animations in this way is called a + \emph{sync base}. +\end{command} + +\begin{command}{\pgfsysanimkeysyncend\marg{sync base id}\marg{type}\marg{time offset}\marg{begin or end}} +\end{command} +\begin{command}{\pgfsys@animation@syncend\marg{sync base id}\marg{type}\marg{time offset}\marg{begin or end}} + Works like |\pgfsysanimkeysyncbegin| only the animation begin (or ends) + when the sync base ends. +\end{command} + +\begin{command}{\pgfsysanimkeyevent\marg{id}\marg{type}\marg{event name}\marg{time offset}\marg{begin or end}} +\end{command} +\begin{command}{\pgfsys@animation@event\marg{id}\marg{type}\marg{event name}\marg{time offset}\marg{begin or end}} + Specifies that the animation should begin (or end) \meta{time offset} many + seconds after a certain \emph{event} has occurred. Which events are + possible depends on the specific output language, here are the events + currently supported in \textsc{svg}: + % + \begin{itemize} + \item |click| occurs when the object with the given \meta{id} and + \meta{type} has been clicked. + \item |focusin| and |focusout| occur when the focus enters or leaves + the object. + \item |mouseup|, |mousedown|, |mouseover|, |mousemove|, and |mouseout| + occur when the mouse is pressed up or down on the object, moved + onto the object, moved over the object, or moved off the object. + \end{itemize} + % +\begin{codeexample}[ + width=2cm, + preamble={\usetikzlibrary{animations}}, +] +\animationexample{node}{}{ + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvaltranslate{0cm}{0cm} + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvaltranslate{0cm}{-1cm} + \pgfsysanimkeyevent{\nodeid}{}{mouseup}{}{begin} + \pgfsysanimate{translate} } +\end{codeexample} + % +\begin{codeexample}[ + width=2cm, + preamble={\usetikzlibrary{animations}}, +] +\animationexample{node}{}{ + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvaltranslate{0cm}{0cm} + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvaltranslate{0cm}{-1cm} + \pgfsysanimkeyevent{\nodeid}{}{mousedown}{}{begin} + \pgfsysanimate{translate} } +\end{codeexample} + % +\begin{codeexample}[ + width=2cm, + preamble={\usetikzlibrary{animations}}, +] +\animationexample{node}{}{ + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvaltranslate{0cm}{0cm} + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvaltranslate{0cm}{-1cm} + \pgfsysanimkeyevent{\nodeid}{}{mouseover}{}{begin} + \pgfsysanimate{translate} } +\end{codeexample} + % +\begin{codeexample}[ + width=2cm, + preamble={\usetikzlibrary{animations}}, +] +\animationexample{node}{}{ + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvaltranslate{0cm}{0cm} + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvaltranslate{0cm}{-1cm} + \pgfsysanimkeyevent{\nodeid}{}{mousemove}{}{begin} + \pgfsysanimate{translate} } +\end{codeexample} + % +\begin{codeexample}[ + width=2cm, + preamble={\usetikzlibrary{animations}}, +] +\animationexample{node}{}{ + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvaltranslate{0cm}{0cm} + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvaltranslate{0cm}{-1cm} + \pgfsysanimkeyevent{\nodeid}{}{mouseout}{}{begin} + \pgfsysanimate{translate} } +\end{codeexample} + % +\end{command} + +\begin{command}{\pgfsysanimkeyrepeatevent\marg{id}\marg{type}\marg{repeat count}\marg{time offset}\marg{begin or end}} +\end{command} +\begin{command}{\pgfsys@animation@repeat@event\marg{id}\marg{type}\marg{repeat count}\marg{time offset}\marg{begin or end}} + The animation begins (or end) with a certain offset when another animation + has reached a certain repeat count. + % +\begin{codeexample}[ + width=6cm, + preamble={\usetikzlibrary{animations}}, + animation list={1,2,3,4,5,6,7,8}, +] +\animationexample{node}{}{ + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvaltranslate{0cm}{0cm} + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvaltranslate{0cm}{-5mm} + \pgfsysanimkeyrepeatdur{5} + \pgfsys@new@id{\animationid} + \pgfsys@use@id{\animationid} + \pgfsysanimate{translate} + \global\let\animationid\animationid } +\tikz { + \pgfidrefnextuse{\objid}{other} + \pgfsysanimkeyrepeatevent{\animationid}{}{2}{0}{begin} + \pgfsysanimkeysnapshotstart{4} + \pgfsysanimkeywhom{\objid}{} + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvaltranslate{0cm}{0cm} + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvaltranslate{0cm}{-5mm} + \pgfsysanimate{translate} + \node [fill=red, text=white, circle] (other) {Other}; } +\end{codeexample} + % +\end{command} + +\begin{command}{\pgfsysanimkeyaccesskey\marg{character}\marg{time offset}\marg{begin or end}} +\end{command} +\begin{command}{\pgfsys@animation@accesskey\marg{character}\marg{time offset}\marg{begin or end}} + Begin or end the animation when a certain key is pressed. Note that this + event may not be supported by some browsers for security reasons (prevent + key loggers). + % +\begin{codeexample}[ + width=2cm, + preamble={\usetikzlibrary{animations}}, +] +\animationexample{node}{}{ + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvaltranslate{0cm}{0cm} + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvaltranslate{0cm}{-1cm} + \pgfsysanimkeyaccesskey{s}{}{begin} + \pgfsysanimate{translate} +} +\end{codeexample} + % +\end{command} + + +\subsection{Commands for Specifying Timing: Restart Behaviour} + +\begin{command}{\pgfsysanimkeyrestartalways} +\end{command} +\begin{command}{\pgfsys@animation@restart@always} + Defines that the animation can be restarted at any time. This is the + default. + % +\begin{codeexample}[ + width=2cm, + preamble={\usetikzlibrary{animations}}, +] +\animationexample{node}{}{ + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvaltranslate{0cm}{0cm} + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvaltranslate{0cm}{-1cm} + \pgfsysanimkeyrestartalways + \pgfsysanimate{translate} } +\end{codeexample} + % +\end{command} + +\begin{command}{\pgfsysanimkeyrestartnever} +\end{command} +\begin{command}{\pgfsys@animation@restart@never} + Defines that the animation cannot be restarted once it has run. + % +\begin{codeexample}[ + width=2cm, + preamble={\usetikzlibrary{animations}}, +] +\animationexample{node}{}{ + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvaltranslate{0cm}{0cm} + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvaltranslate{0cm}{-1cm} + \pgfsysanimkeyrestartnever + \pgfsysanimate{translate} } +\end{codeexample} + % +\end{command} + +\begin{command}{\pgfsysanimkeyrestartwhennotactive} +\end{command} +\begin{command}{\pgfsys@animation@restart@whennotactive} + Defines that the animation cannot be restarted while it is running. + % +\begin{codeexample}[ + width=2cm, + preamble={\usetikzlibrary{animations}}, +] +\animationexample{node}{}{ + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvaltranslate{0cm}{0cm} + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvaltranslate{0cm}{-1cm} + \pgfsysanimkeyrestartwhennotactive + \pgfsysanimate{translate} } +\end{codeexample} + % +\end{command} + +\begin{command}{\pgfsysanimkeyfreezeatend} +\end{command} +\begin{command}{\pgfsys@animation@freezeatend} + When an animation ends, the question is whether the ``effect'' of the + animation (like changing a color or translating the coordinate system) + should disappear or ``remain in force''. Using this key, you specify that + at the end of the animation the last value of the attributes stays in + effect. + % +\begin{codeexample}[ + width=6cm, + preamble={\usetikzlibrary{animations}}, + animation list={1,2,3,4,5,6,7,8}, +] +\animationexample{node}{}{ + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvaltranslate{0cm}{0cm} + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvaltranslate{0cm}{-1cm} + \pgfsysanimkeyfreezeatend + \pgfsysanimate{translate} } +\end{codeexample} + % +\end{command} + +\begin{command}{\pgfsysanimkeyremoveatend} +\end{command} +\begin{command}{\pgfsys@animation@removeatend{}} + The opposite of |\pgfsysanimkeyfreezeatend|. This is the default. + % +\begin{codeexample}[ + width=6cm, + preamble={\usetikzlibrary{animations}}, + animation list={1,2,3,4,5,6,7,8}, +] +\animationexample{node}{}{ + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvaltranslate{0cm}{0cm} + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvaltranslate{0cm}{-1cm} + \pgfsysanimkeyremoveatend + \pgfsysanimate{translate} } +\end{codeexample} + % +\end{command} + + +\subsection{Commands for Specifying Accumulation} + +Animations specify how an attribute of an object changes over time. When more +than one animation changes the same value at the same time, the last value +given for the attribute ``wins'', except for animations of the canvas, which +always accumulate. Additionally, when a repeat is specified for an attribute, +during each repeat the values can add up: + +\begin{command}{\pgfsysanimkeyaccumulate{}} +\end{command} +\begin{command}{\pgfsys@animation@accumulate{}} + Specifies that each repeat of an animation works as if the last values + attained during previous repeats are added to the current value. + % +\begin{codeexample}[ + width=6cm, + preamble={\usetikzlibrary{animations}}, + animation list={1,2,3,4,5,6,7,8}, +] +\animationexample{node}{}{ + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvaltranslate{0cm}{0cm} + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvaltranslate{0cm}{-5mm} + \pgfsysanimkeyaccumulate + \pgfsysanimkeyrepeatdur{5} + \pgfsysanimate{translate} } +\end{codeexample} + % +\end{command} + +\begin{command}{\pgfsysanimkeynoaccumulate{}} +\end{command} +\begin{command}{\pgfsys@animation@noaccumulate{}} + Specifies that each repeat resets the to-be-animated value. This is the + default. + % +\begin{codeexample}[ + width=6cm, + preamble={\usetikzlibrary{animations}}, + animation list={1,2,3,4,5,6,7,8}, +] +\animationexample{node}{}{ + \pgfsysanimkeytime{0}{1}{1}{0}{0} + \pgfsysanimvaltranslate{0cm}{0cm} + \pgfsysanimkeytime{2}{1}{1}{0}{0} + \pgfsysanimvaltranslate{0cm}{-5mm} + \pgfsysanimkeynoaccumulate + \pgfsysanimkeyrepeatdur{5} + \pgfsysanimate{translate} } +\end{codeexample} + % +\end{command} + + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: "pgfmanual" +%%% End: |