% Copyright 2015 by Till Tantau % % This file may be distributed and/or modified % % 1. under the LaTeX Project Public License and/or % 2. under the GNU Public License. % % See the file doc/generic/pgf/licenses/LICENSE for more details. \ProvidesFileRCS{pgfmoduleanimations.code.tex} % We need the animation system abstraction: \input pgfsysanimations.code.tex % Animate an attribute over time % % #1 = an attribute % #2 = configuration keys % % This command adds animation commands for the attribute given in #1 % of some future object to the current graphic scope. For instance, % when #1 is "fill opacity" then the fill opacity of the object will % change over time. The object to which the command refers is % specified using a special key in #2. % % The keys in #2 specify how the changes occur over time. There are a % number of keys that have an effect on the animation "as a whole" % (like "repeats") while the most central key is the entry key. This % key takes two parameters: a time and a value. It specifies that at % the given time the attribute should have the specified value. The % times must be given in ascending order. Between the times given in % this way, the values of the attribute will be interpolated; you can % influence the details of how this interpolation is done using % additional keys. % % The keys in #2 are given in key-value syntax and can be given in any % order, except that the entry keys must be given in order of % ascending times. % % The syntax of the second parameter of the entry key depends on % #1. Currently, these are: % % Attribute Value Type % --------------------------------------- % fill opacity scalar % stroke opacity scalar % opacity scalar % visible boolean % line width dimension % fill color % stroke color % motion motion % translate point % scale scaling % rotate scalar % xskew scalar % yskew scalar % path path % softpath softpath % view viewbox % dash phase dimension % dash pattern dashpattern % none any % % Example: % % \pgfanimateattribute{fill opacity}{entry={0s}{1}, entry={2s}{0}} \def\pgfanimateattribute#1#2{% \pgfanimateattributecode{#1}{\pgfkeys{/pgf/animation/.cd,#2}}% } % Variant of \pgfanimateattribute % % #1 = attribute % #2 = code % % Description: % % A version of \pgfanimateattribute where instead of keys #2 you % provide a code #2 that calls the animation keys itself. \def\pgfanimateattributecode#1#2{% {% \pgfkeys{/pgf/@animation attributes/.cd,#1}% #2% \csname pgf@animation@check@\pgf@animation@attribute\endcsname% \pgfsysanimate{\pgf@animation@attribute}% }% } % Create a time snapshot % % #1 = a time % % Description: % % This command should be called in a scope prior to all calls of % animation commands in that scope. When called, all animations will % be "intercepted" and, instead of creating the animation code, normal % code will be generated that shows the state of the animation at the % specified "moment" #1. Since no animation code is involved, this % works with all drivers. % % The command \pgfsnapshotafter works the same way as \pgfsnapshot, % only the timing is slightly different: Conceptually, #1 is % interpreted as "#1+epsilon". For instance, if there are two values % specified for the time #1, then \pgfsnapshot will use the first % while \pgfsnapshotafter will use the second. Likewise, when an % animation ends at time #1, \pgfsnapshot will still us the % animation's value, while \pgfsnapshotafter will not. % % Example: % % { % \pgfsnapshot{1.2s} % \pgfanimateattribute{fill opacity}{entry={0s}{1}, entry={2s}{0}} % \fill (0,0) rectangle (1,1); % } \def\pgfsnapshot#1{\pgfparsetime{#1}\expandafter\pgfsysanimsnapshot\expandafter{\pgftimeresult}} \def\pgfsnapshotafter#1{\pgfparsetime{#1}\expandafter\pgfsysanimsnapshotafter\expandafter{\pgftimeresult}} % The animation attributes \pgfkeys{/pgf/@animation attributes/.cd, visible/.code=\pgf@animate@attr{visibility}{mapped}\def\pgf@anim@map@true{visible}\def\pgf@anim@map@false{hidden}, stage/.code=\pgf@animate@attr{visibility}{mapped}\def\pgf@anim@map@true{visible}\def\pgf@anim@map@false{hidden}\pgfsysanimkeybase\pgfsysanimvaltext{hidden}, opacity/.code=\pgf@animate@attr{opacity}{scalar}, fill opacity/.code=\pgf@animate@attr{fillopacity}{scalar}, draw opacity/.code=\pgf@animate@attr{strokeopacity}{scalar}, stroke opacity/.style=draw opacity, line width/.code=\pgf@animate@attr{linewidth}{dimension}, fill/.code=\pgf@animate@attr{fillcolor}{color}, draw/.code=\pgf@animate@attr{strokecolor}{color}, color/.code=\pgf@animate@attr{color}{color}, stroke/.style=draw, motion/.code=\pgf@animate@attr{motion}{scalar}, translate/.code=\pgf@animate@attr{translate}{point}, scale/.code=\pgf@animate@attr{scale}{scaling}, rotate/.code=\pgf@animate@attr{rotate}{scalar}, xskew/.code=\pgf@animate@attr{skewx}{scalar}, yskew/.code=\pgf@animate@attr{skewy}{scalar}, skew x/.style=xskew, skew y/.style=yskew, path/.code=\pgf@animate@attr{path}{path}, softpath/.code=\pgf@animate@attr{path}{softpath}, view/.code=\pgf@animate@attr{viewbox}{viewbox}, dash/.code=\pgf@animate@attr{dash}{dash}, none/.code=\pgf@animate@attr{none}{none}, } \def\pgf@animate@attr#1#2{% \def\pgf@animation@attribute{#1}% \expandafter\let\expandafter\pgfanim@type@parser\csname pgfanim@parse@type@#2\endcsname% } % The time parser % % #1 = a time % % This macro parses the time in #1, but adds some support for times: % % 1) The postfix operator "s" is added, which has no effect. % 2) The postfix operator "ms" is added, which devides a number by % 1000, so "2ms" equals "0.002". % 3) The postfix operator "min" is added, which multiplies a number by % 60. % 4) The postfix operator "h" is added, which multiplies a number by % 3600. % 5) The infix operator ":" is redefined, so that it multiplies its % first argument by 60 and adds the second. This implies that % "1:20" equals "80" and "01:00:00" equals "3600". % 6) The parsing of octal numbers is switched off to allow things like % "01:08" for 68s. \def\pgfparsetime#1{% \begingroup% \pgfmathdeclareoperator{s}{@seconds}{1}{postfix}{600}% \pgfmathdeclareoperator{m}{m@encountered}{1}{postfix}{600}% \pgfmathdeclareoperator{i}{i@encountered}{1}{postfix}{600}% \pgfmathdeclareoperator{n}{@minutes}{1}{postfix}{600}% \pgfmathdeclareoperator{h}{@hours}{1}{postfix}{600}% \pgfmathdeclareoperator{:}{time@colon}{2}{infix}{50}% \pgfmath@octalparsingfalse% \pgfmathparse{#1}% \expandafter\endgroup% \expandafter\def\expandafter\pgftimeresult\expandafter{\pgfmathresult}% } \newif\ifpgfanim@m@encountered \newif\ifpgfanim@i@encountered \pgfmathdeclarefunction{@seconds}{1}{% \begingroup% \expandafter\pgfmath@x#1pt\relax% \ifpgfanim@m@encountered% \divide\pgfmath@x by1000\relax% \fi% \global\pgfanim@m@encounteredfalse% \pgfmath@returnone\pgfmath@x% \endgroup% }% \pgfmathdeclarefunction{m@encountered}{1}{% \global\pgfanim@m@encounteredtrue% \begingroup% \expandafter\pgfmath@x#1pt\relax% \pgfmath@returnone\pgfmath@x% \endgroup% }% \pgfmathdeclarefunction{i@encountered}{1}{% \ifpgfanim@m@encountered% \global\pgfanim@m@encounteredfalse% \global\pgfanim@i@encounteredtrue% \else% \pgfmath@error{Unexpected i}{}% \fi% \begingroup% \expandafter\pgfmath@x#1pt\relax% \pgfmath@returnone\pgfmath@x% \endgroup% }% \pgfmathdeclarefunction{@minutes}{1}{% \ifpgfanim@i@encountered% \global\pgfanim@i@encounteredfalse% \else% \pgfmath@error{Unexpected n}{}% \fi% \begingroup% \expandafter\pgfmath@x#1pt\relax% \pgfmath@x60\pgfmath@x\relax% \pgfmath@returnone\pgfmath@x% \endgroup% }% \pgfmathdeclarefunction{@hours}{1}{% \begingroup% \expandafter\pgfmath@x#1pt\relax% \pgfmath@x3600\pgfmath@x\relax% \pgfmath@returnone\pgfmath@x% \endgroup% }% \pgfmathdeclarefunction{time@colon}{2}{% \begingroup% \pgfmath@x=#1pt\relax% \pgfmath@x=60\pgfmath@x\relax% \pgfmath@y=#2pt\relax% \advance\pgfmath@x by\pgfmath@y% \pgfmath@returnone\pgfmath@x% \endgroup% } % Sets general animation attributes % % #1 = key-value pairs that are executed for the path /pgf/animation/ \def\pgfanimationset{\pgfqkeys{/pgf/animation}} % Sets the target animation scope that should be animated. % % #1 = A name that will be used with an idscope. % % Example: % % \pgfanimateattribute{fill opacity}{whom=some scope, entry={0s}{1}, entry={1s}{0}} % \begin{scope}[name=some scope] % \draw (0,0) -- (1,1); % \draw (1,0) -- (2,1); % \end{scope} \pgfanimationset{ whom/.code={% \pgf@anim@decomp{#1}% \pgfidrefnextuse\pgf@anim@id\pgf@anim@id@name% \expandafter\expandafter\expandafter\pgfsysanimkeywhom\expandafter\expandafter\expandafter{\expandafter\pgf@anim@id\expandafter}\expandafter{\pgf@anim@type}% \let\pgf@anim@whom@id\pgf@anim@id% \let\pgf@anim@whom@type\pgf@anim@type% } } \def\pgf@anim@decomp#1{% \edef\pgf@temp{#1}% \expandafter\pgfutil@in@\expandafter.\expandafter{\pgf@temp}% \ifpgfutil@in@% \expandafter\pgf@anim@decomp@\pgf@temp\pgf@stop% \else% \expandafter\pgf@anim@decomp@\pgf@temp.\pgf@stop% \fi% } \def\pgf@anim@decomp@#1.#2\pgf@stop{% \def\pgf@anim@id@name{#1}% \def\pgf@anim@type{#2}% } % Assigns a name to this animation so that it can be used as an event % id in another animation % % #1 = A name % % The name "previous" is special and always refers to the most recent % animation before the animation currently being constructed. % % Example: % % \pgfanimateattribute{fill opacity}{name=anim 1, entry={0s}{1}, entry={1s}{0}} % \pgfanimateattribute{fill opacity}{begin on={end,of=anim 1}, entry={0s}{1}, entry={1s}{0}} \pgfanimationset{ name/.code=\pgfuseid{#1} } % Configures whether an animation can be restarted % % Some animations can restart when certain events take place. This key % configures this. Setting it to % % "true" allows a restart at any time, % "false" does not allow a restart, % "when not active" allows a restart only, when the element is not % active. % % Example: % % \pgfanimateattribute{fill opacity}{entry={0s}{1}, entry={1s}{0}, restart=false} \pgfanimationset{ restart/.is choice, restart/.default=true, restart/true/.code=\pgfsysanimkeyrestartalways, restart/false/.code=\pgfsysanimkeyrestartnever, restart/never/.code=\pgfsysanimkeyrestartnever, restart/when not active/.code=\pgfsysanimkeyrestartwhennotactive } % Sets the number times an animation should repeat % % #1 = A string of the following form: % % [ | | for